/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
//
%token_type {Token}
%default_type {Token}

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *pParse}

// This code runs whenever there is a syntax error
//
%syntax_error {
  UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings */
  assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
  sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
}
%stack_overflow {
  UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */
  sqlite3ErrorMsg(pParse, "parser stack overflow");
}

// The name of the generated procedure that implements the parser
// is as follows:
%name sqlite3Parser

%ifdef MAXSCALE
%include {
#ifdef MAXSCALE
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
#error sqlite3 for MaxScale should be built with SQLITE_ENABLED_DELETE_LIMIT defined.
#endif
#endif
}
%endif

// The following text is included near the beginning of the C source
// code file that implements the parser.
//
%include {
#include "sqliteInt.h"

// Copied from parser.hh
enum
{
  QUERY_TYPE_READ               = 1 << 1, /*< Read database data:any */
  QUERY_TYPE_WRITE              = 1 << 2, /*< Master data will be  modified:master */
  QUERY_TYPE_USERVAR_READ       = 1 << 6, /*< Read a user variable:master or any */
};

typedef enum qc_field_usage
{
    QC_USED_IN_SELECT    = 0x01, /*< SELECT fld FROM... */
    QC_USED_IN_SUBSELECT = 0x02, /*< SELECT 1 FROM ... SELECT fld ... */
    QC_USED_IN_WHERE     = 0x04, /*< SELECT ... FROM ... WHERE fld = ... */
    QC_USED_IN_SET       = 0x08, /*< UPDATE ... SET fld = ... */
    QC_USED_IN_GROUP_BY  = 0x10, /*< ... GROUP BY fld */
} qc_field_usage_t;

// MaxScale naming convention:
//
// - A function that "overloads" a sqlite3 function has the same name
//   as the function it overloads, prefixed with "mxs_".
// - A function that is new for MaxScale has the name "maxscaleXYZ"
//   where "XYZ" reflects the statement the function handles.
//
extern void mxs_sqlite3AlterFinishAddColumn(Parse *, Token *);
extern void mxs_sqlite3AlterBeginAddColumn(Parse *, SrcList *);
extern void mxs_sqlite3Analyze(Parse *, SrcList *);
extern void mxs_sqlite3BeginTransaction(Parse*, mxs_begin_t, int token, int type);
extern void mxs_sqlite3CommitTransaction(Parse*);
extern void mxs_sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                                   Expr*, int, int);
extern void mxs_sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
                                    Expr*,int, int);
extern void mxs_sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
extern void mxs_sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
extern void mxs_sqlite3DeleteFrom(Parse* pParse, SrcList* pTabList, Expr* pWhere, SrcList* pUsing);
extern void mxs_sqlite3DropIndex(Parse*, SrcList*, SrcList*,int);
extern void mxs_sqlite3DropTable(Parse*, SrcList*, int, int, int);
extern void mxs_sqlite3EndTable(Parse*, Token*, Token*, u8, Select*, SrcList*);
extern void mxs_sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int,ExprList*);
extern void mxs_sqlite3RollbackTransaction(Parse*);
extern void mxs_sqlite3Savepoint(Parse *pParse, int op, Token *pName);
extern int  mxs_sqlite3Select(Parse*, Select*, SelectDest*);
extern void mxs_sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
extern void mxs_sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);

extern void maxscaleCollectInfoFromSelect(Parse*, Select*, int);

extern void maxscaleAlterTable(Parse*, mxs_alter_t command, SrcList*, Token*);
extern void maxscaleCall(Parse*, SrcList* pName, ExprList* pExprList);
extern void maxscaleCheckTable(Parse*, SrcList* pTables);
extern void maxscaleCreateSequence(Parse*, Token* pDatabase, Token* pTable);
extern void maxscaleDeclare(Parse* pParse);
extern void maxscaleDeallocate(Parse*, Token* pName);
extern void maxscaleDo(Parse*, ExprList* pEList);
extern void maxscaleDrop(Parse*, int what, Token* pDatabase, Token* pName);
extern void maxscaleExecute(Parse*, Token* pName, int type_mask);
extern void maxscaleExecuteImmediate(Parse*, Token* pName, ExprSpan* pExprSpan, int type_mask);
extern void maxscaleExplainTable(Parse*, SrcList* pList);
extern void maxscaleExplain(Parse*);
extern void maxscaleFlush(Parse*, Token* pWhat);
extern void maxscaleHandler(Parse*, mxs_handler_t, SrcList* pFullName, Token* pName);
extern void maxscaleLoadData(Parse*, SrcList* pFullName, int local);
extern void maxscaleLock(Parse*, mxs_lock_t, SrcList*);
extern void maxscaleOptimize(Parse*, SrcList*);
extern void maxscaleOracleAssign(Parse*, Token* pVariable, Expr* pValue);
extern void maxscaleKill(Parse*, MxsKill*);
extern void maxscalePrepare(Parse*, Token* pName, Expr* pStmt);
extern void maxscalePrivileges(Parse*, int kind);
extern void maxscaleRenameTable(Parse*, SrcList* pTables);
extern void maxscaleReset(Parse*, int what);
extern void maxscaleSet(Parse*, int scope, mxs_set_t kind, ExprList*);
extern void maxscaleSetPassword(Parse*);
extern void maxscaleSetTransaction(Parse*, int scope, int access_mode);
extern void maxscaleSetVariable(Parse*, int scope, Expr*);
extern void maxscaleShow(Parse*, MxsShow* pShow);
extern void maxscaleTruncate(Parse*, Token* pDatabase, Token* pName);
extern void maxscaleUse(Parse*, Token*);

extern void maxscale_update_function_info(const char* name, const Expr* pExpr);
extern void maxscale_set_type_mask(unsigned int type_mask);

static Expr* maxscale_create_pseudo_limit(Parse* pParse, Token* pToken, ExprSpan* pLimit);

// Exposed utility functions
void exposed_sqlite3ExprDelete(sqlite3 *db, Expr *pExpr)
{
  sqlite3ExprDelete(db, pExpr);
}

void exposed_sqlite3ExprListDelete(sqlite3 *db, ExprList *pList)
{
  sqlite3ExprListDelete(db, pList);
}

void exposed_sqlite3IdListDelete(sqlite3 *db, IdList *pList)
{
  sqlite3IdListDelete(db, pList);
}

void exposed_sqlite3SelectDelete(sqlite3 *db, Select *p)
{
  sqlite3SelectDelete(db, p);
}

void exposed_sqlite3SrcListDelete(sqlite3 *db, SrcList *pList)
{
  sqlite3SrcListDelete(db, pList);
}


// Exposed SQL functions.
void exposed_sqlite3BeginTrigger(Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
                                 Token *pName1,      /* The name of the trigger */
                                 Token *pName2,      /* The name of the trigger */
                                 int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
                                 int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
                                 IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
                                 SrcList *pTableName,/* The name of the table/view the trigger applies to */
                                 Expr *pWhen,        /* WHEN clause */
                                 int isTemp,         /* True if the TEMPORARY keyword is present */
                                 int noErr)          /* Suppress errors if the trigger already exists */
{
  sqlite3BeginTrigger(pParse, pName1, pName2, tr_tm, op, pColumns, pTableName, pWhen, isTemp, noErr);
}

void exposed_sqlite3FinishTrigger(Parse *pParse,
                                  TriggerStep *pStepList,
                                  Token *pAll)
{
  sqlite3FinishTrigger(pParse, pStepList, pAll);
}

int exposed_sqlite3Dequote(char *z)
{
  return sqlite3Dequote(z);
}

void exposed_sqlite3Insert(Parse* pParse,
                           SrcList* pTabList,
                           Select* pSelect,
                           IdList* pColumns,
                           int onError)
{
  sqlite3Insert(pParse, pTabList, pSelect, pColumns, onError);
}

void exposed_sqlite3EndTable(Parse* pParse, Token* pCons, Token* pEnd, u8 tabOpts, Select* pSelect)
{
  sqlite3EndTable(pParse, pCons, pEnd, tabOpts, pSelect);
}

int exposed_sqlite3Select(Parse* pParse, Select* p, SelectDest* pDest)
{
  return sqlite3Select(pParse, p, pDest);
}

void exposed_sqlite3StartTable(Parse *pParse,   /* Parser context */
                               Token *pName1,   /* First part of the name of the table or view */
                               Token *pName2,   /* Second part of the name of the table or view */
                               int isTemp,      /* True if this is a TEMP table */
                               int isView,      /* True if this is a VIEW */
                               int isVirtual,   /* True if this is a VIRTUAL table */
                               int noErr)       /* Do nothing if table already exists */
{
  sqlite3StartTable(pParse, pName1, pName2, isTemp, isView, isVirtual, noErr);
}

void exposed_sqlite3Update(Parse* pParse, SrcList* pTabList, ExprList* pChanges, Expr* pWhere, int onError)
{
    sqlite3Update(pParse, pTabList, pChanges, pWhere, onError);
}

/*
** Disable all error recovery processing in the parser push-down
** automaton.
*/
#define YYNOERRORRECOVERY 1

/*
** Make yytestcase() the same as testcase()
*/
#define yytestcase(X) testcase(X)

/*
** Indicate that sqlite3ParserFree() will never be called with a null
** pointer.
*/
#define YYPARSEFREENEVERNULL 1

/*
** Alternative datatype for the argument to the malloc() routine passed
** into sqlite3ParserAlloc().  The default is size_t.
*/
#define YYMALLOCARGTYPE  u64

/*
** An instance of this structure holds information about the
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
  Expr *pLimit;    /* The LIMIT expression.  NULL if there is no limit */
  Expr *pOffset;   /* The OFFSET expression.  NULL if there is none */
};

/*
** An instance of this structure is used to store the LIKE,
** GLOB, NOT LIKE, and NOT GLOB operators.
*/
struct LikeOp {
  Token eOperator;  /* "like" or "glob" or "regexp" */
  int bNot;         /* True if the NOT keyword is present */
};

/*
** An instance of the following structure describes the event of a
** TRIGGER.  "a" is the event type, one of TK_UPDATE, TK_INSERT,
** TK_DELETE, or TK_INSTEAD.  If the event is of the form
**
**      UPDATE ON (a,b,c)
**
** Then the "b" IdList records the list "a,b,c".
*/
struct TrigEvent { int a; IdList * b; };

/*
** An instance of this structure holds the ATTACH key and the key type.
*/
struct AttachKey { int type;  Token key; };

/*
** Disable lookaside memory allocation for objects that might be
** shared across database connections.
*/
static void disableLookaside(Parse *pParse){
  pParse->disableLookaside++;
  pParse->db->lookaside.bDisable++;
}

} // end %include

// Input is a single SQL command
input ::= cmdlist.
cmdlist ::= cmdlist ecmd.
cmdlist ::= ecmd.
ecmd ::= SEMI.
ecmd ::= explain SEMI.
ecmd ::= cmdx SEMI.
ecmd ::= oracle_assignment SEMI.
%ifdef MAXSCALE
explain_kw ::= EXPLAIN.  // Also covers DESCRIBE
explain_kw ::= DESC.

explain ::= explain_kw tbl_name(A). { pParse->explain = 1; maxscaleExplainTable(pParse, A); }
explain_type ::= .
explain_type ::= EXTENDED.
explain_type ::= PARTITIONS.
// deferred_id is defined later, after the id token_class has been defined.
explain_type ::= FORMAT TK_EQ deferred_id. // FORMAT = {TRADITIONAL|JSON}

explain ::= explain_kw explain_type FOR CONNECTION INTEGER. { // FOR CONNECTION connection_id
  pParse->explain = 1;
  maxscaleExplain(pParse);
}
%endif
%ifndef SQLITE_OMIT_EXPLAIN
%ifndef MAXSCALE
explain ::= EXPLAIN QUERY PLAN.   { pParse->explain = 2; }
%endif
%endif  SQLITE_OMIT_EXPLAIN
cmdx ::= cmd.           { sqlite3FinishCoding(pParse); }

///////////////////// Begin and end transactions. ////////////////////////////
//

%ifdef MAXSCALE
work_opt ::= WORK.
work_opt ::= .
cmd ::= BEGIN work_opt. {
  mxs_sqlite3BeginTransaction(pParse, MXS_BEGIN_TRANSACTION, TK_BEGIN, 0);
} // BEGIN [WORK]
cmd ::= BEGIN NOT ATOMIC. {mxs_sqlite3BeginTransaction(pParse, MXS_BEGIN_NOT_ATOMIC, TK_BEGIN, 0);}
%endif
%ifndef MAXSCALE
cmd ::= BEGIN transtype(Y) trans_opt.  {sqlite3BeginTransaction(pParse, Y);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
trans_opt ::= TRANSACTION nm.
%type transtype {int}
transtype(A) ::= .             {A = TK_DEFERRED;}
transtype(A) ::= DEFERRED(X).  {A = @X;}
transtype(A) ::= IMMEDIATE(X). {A = @X;}
transtype(A) ::= EXCLUSIVE(X). {A = @X;}
%endif
%ifdef MAXSCALE
cmd ::= COMMIT work_opt.       {mxs_sqlite3CommitTransaction(pParse);}
cmd ::= ROLLBACK work_opt.     {mxs_sqlite3RollbackTransaction(pParse);}
%endif
%ifndef MAXSCALE
cmd ::= COMMIT trans_opt.      {sqlite3CommitTransaction(pParse);}
cmd ::= END trans_opt.         {sqlite3CommitTransaction(pParse);}
cmd ::= ROLLBACK trans_opt.    {sqlite3RollbackTransaction(pParse);}
%endif

%ifdef MAXSCALE
savepoint_opt ::= SAVEPOINT.
savepoint_opt ::= .
cmd ::= SAVEPOINT nm(X). {
  mxs_sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &X);
}
cmd ::= RELEASE savepoint_opt nm(X). {
  mxs_sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X);
}
cmd ::= ROLLBACK work_opt TO savepoint_opt nm(X). {
  mxs_sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X);
}
%endif

%ifndef MAXSCALE
savepoint_opt ::= SAVEPOINT.
savepoint_opt ::= .
cmd ::= SAVEPOINT nm(X). {
  sqlite3Savepoint(pParse, SAVEPOINT_BEGIN, &X);
}
cmd ::= RELEASE savepoint_opt nm(X). {
  sqlite3Savepoint(pParse, SAVEPOINT_RELEASE, &X);
}
cmd ::= ROLLBACK trans_opt TO savepoint_opt nm(X). {
  sqlite3Savepoint(pParse, SAVEPOINT_ROLLBACK, &X);
}
%endif

///////////////////// The CREATE TABLE statement ////////////////////////////
//
cmd ::= create_table create_table_args.
create_table ::= createkw temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). {
#ifdef MAXSCALE
   mxs_sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
#else
   sqlite3StartTable(pParse,&Y,&Z,T,0,0,E);
#endif
}
%ifdef MAXSCALE
or_replace_opt ::= .
or_replace_opt ::= OR REPLACE.

createkw(A) ::= CREATE(X) or_replace_opt.  {
  disableLookaside(pParse);
  A = X;
}
%endif
%ifndef MAXSCALE
createkw(A) ::= CREATE(X).  {
  disableLookaside(pParse);
  A = X;
}
%endif
%type ifnotexists {int}
ifnotexists(A) ::= .              {A = 0;}
ifnotexists(A) ::= IF NOT EXISTS. {A = 1;}
%type temp {int}
%ifndef SQLITE_OMIT_TEMPDB
temp(A) ::= TEMP.  {A = 1;}
%endif  SQLITE_OMIT_TEMPDB
temp(A) ::= .      {A = 0;}
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
#ifdef MAXSCALE
  mxs_sqlite3EndTable(pParse,&X,&E,F,0,0);
#else
  sqlite3EndTable(pParse,&X,&E,F,0);
#endif
}
%ifdef MAXSCALE
create_table_args ::= table_options(F) as_opt select(S). {
  mxs_sqlite3EndTable(pParse,0,0,F,S,0);
  sqlite3SelectDelete(pParse->db, S);
}

ignore_or_replace_opt ::= .
ignore_or_replace_opt ::= IGNORE.
ignore_or_replace_opt ::= REPLACE.

create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F)
                      ignore_or_replace_opt as_opt select(S). {
  mxs_sqlite3EndTable(pParse,&X,&E,F,S,0);
  sqlite3SelectDelete(pParse->db, S);
}

create_table_args ::= LIKE_KW fullname(X). {
  mxs_sqlite3EndTable(pParse,0,0,0,0,X);
}

%endif
%ifndef MAXSCALE
create_table_args ::= AS select(S). {
  sqlite3EndTable(pParse,0,0,0,S);
  sqlite3SelectDelete(pParse->db, S);
}
%endif
%type table_option {int}
%type table_options {int}
table_options(A) ::= .    {A = 0;}
%ifdef MAXSCALE
table_options(A) ::= table_options(B) table_option(C). {A = B|C;}
table_option(A) ::= ENGINE eq_opt nm. {A = 0;}
table_option(A) ::= AUTOINCR eq_opt INTEGER. {A = 0;}
table_option(A) ::= default_opt CHARSET eq_opt nm. {A = 0;}
table_option(A) ::= default_opt CHARACTER SET eq_opt nm. {A = 0;}
table_option(A) ::= COMMENT eq_opt STRING. {A = 0;}
table_option(A) ::= ID eq_opt DEFAULT. {A = 0;}
table_option(A) ::= ID eq_opt ID. {A = 0;}
table_option(A) ::= ID eq_opt INTEGER. {A = 0;}
table_option(A) ::= ID eq_opt STRING. {A = 0;}
table_option(A) ::= UNION eq LP fullnames(X) RP. {
  sqlite3SrcListDelete(pParse->db, X);
  A = 0;
}
%endif
%ifndef MAXSCALE
table_options(A) ::= WITHOUT nm(X). {
  if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){
    A = TF_WithoutRowid | TF_NoVisibleRowid;
  }else{
    A = 0;
    sqlite3ErrorMsg(pParse, "unknown table option: %.*s", X.n, X.z);
  }
}
%endif
columnlist ::= columnlist COMMA column.
columnlist ::= column.

// A "column" is a complete description of a single column in a
// CREATE TABLE statement.  This includes the column name, its
// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES,
// NOT NULL and so forth.
//
%ifdef MAXSCALE
column(A) ::= columnid(X) type type_options carglist. {
%endif
%ifndef MAXSCALE
column(A) ::= columnid(X) type carglist. {
%endif
  A.z = X.z;
  A.n = (int)(pParse->sLastToken.z-X.z) + pParse->sLastToken.n;
}

%ifdef MAXSCALE
fulltext_or_spatial ::= FULLTEXT.
fulltext_or_spatial ::= SPATIAL.

index_or_key ::= INDEX.
index_or_key ::= KEY.

index_or_key_opt ::= .
index_or_key_opt ::= index_or_key.

index_name_opt ::= .
index_name_opt ::= index_name.

index_type ::= USING deferred_id. // USING {BTREE|HASH}

index_type_opt ::= .
index_type_opt ::= index_type.

index_option ::= deferred_id INTEGER.          // KEY_BLOCK_SIZE valye
index_option ::= deferred_id eq INTEGER.       // KEY_BLOCK_SIZE = value
index_option ::= index_type.                   // USING {BTREE|HASH}
index_option ::= WITH deferred_id deferred_id. // WITH PARSER parser_name.
index_option ::= COMMENT STRING.               // COMMENT 'string'

index_option_opt ::= .
index_option_opt ::= index_option.

// PRIMARY KEY [index_option] (index_col_name, ...)
column(A) ::= PRIMARY KEY index_option_opt LP index_type_opt sortlist(X) RP index_option_opt. {
  sqlite3ExprListDelete(pParse->db, X);
  A.z = 0;
  A.n = 0;
}

// {INDEX|KEY} [index_name] [index_type] (index_col_name, ...) [index_option]
column(A) ::= index_or_key index_name_opt index_type_opt LP sortlist(X) RP  index_option_opt. {
  sqlite3ExprListDelete(pParse->db, X);
  A.z = 0;
  A.n = 0;
}

// UNIQUE [INDEX|KEY] [index_name] (index_col_name, ...) [index_option]
column(A) ::= UNIQUE index_or_key_opt index_name_opt LP sortlist(X) RP index_option_opt. {
  sqlite3ExprListDelete(pParse->db, X);
  A.z = 0;
  A.n = 0;
}

// {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name, ...)  [index_option]
column(A) ::= fulltext_or_spatial index_or_key_opt index_name_opt LP sortlist(X) RP index_option_opt. {
  sqlite3ExprListDelete(pParse->db, X);
  A.z = 0;
  A.n = 0;
}

// FOREIGN KEY [index_name] LP index_col_name, ... RP reference_definition
column(A) ::= FOREIGN KEY LP eidlist(FA) RP
          REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
    sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
    sqlite3DeferForeignKey(pParse, D);
    A.z = 0;
    A.n = 0;
}

// CHECK (expr)
column(A) ::= CHECK LP expr(X) RP. {
  sqlite3AddCheckConstraint(pParse,X.pExpr);
  A.z = 0;
  A.n = 0;
}

%endif

%ifdef MAXSCALE
columnid(A) ::= nm(X). {
  sqlite3AddColumn(pParse,&X);
  A = X;
  pParse->constraintName.n = 0;
}
columnid(A) ::= nm DOT nm(X). {
  sqlite3AddColumn(pParse,&X);
  A = X;
  pParse->constraintName.n = 0;
}
columnid(A) ::= nm DOT nm DOT nm(X). {
  sqlite3AddColumn(pParse,&X);
  A = X;
  pParse->constraintName.n = 0;
}
%endif
%ifndef MAXSCALE
columnid(A) ::= nm(X). {
  sqlite3AddColumn(pParse,&X);
  A = X;
  pParse->constraintName.n = 0;
}
%endif

// An IDENTIFIER can be a generic identifier, or one of several
// keywords.  Any non-standard keyword can also be an identifier.
//
%token_class id  ID|INDEXED.

// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
//
%fallback ID
%ifndef MAXSCALE
  ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
  CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
  IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
  QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
  ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
%ifdef SQLITE_OMIT_COMPOUND_SELECT
  EXCEPT INTERSECT UNION
%endif SQLITE_OMIT_COMPOUND_SELECT
  REINDEX RENAME CTIME_KW IF
%endif
%ifdef MAXSCALE
  /*ABORT*/ ACTION AFTER ALGORITHM /*ANALYZE*/ /*ASC*/ /*ATTACH*/
  /*BEFORE*/ /*BEGIN*/ BY
  // TODO: BINARY is a reserved word and should not automatically convert into an identifer.
  // TODO: However, if not here then rules such as CAST need to be modified.
  BINARY
  CACHE /*CASCADE*/ CAST CHARSET_NAME_KW CLOSE COLUMNKW COLUMNS COMMENT CONCURRENT /*CONFLICT*/ CONNECTION COMMITTED
  DATA DATABASE DEALLOCATE DEFERRED /*DESC*/ /*DETACH*/ DUMPFILE
  /*EACH*/ END ENGINE ENUM EXCLUSIVE /*EXPLAIN*/ EXTENDED
  FIELDS FIRST FLUSH /*FOR*/ FORMAT
  GLOBAL
  HANDLER HARD
  // TODO: IF is a reserved word and should not automatically convert into an identifer.
  IF IMMEDIATE INITIALLY INSTEAD ISOLATION
  /*KEY*/
  /*LIKE_KW*/
  LOCAL LEVEL
  MASTER /*MATCH*/ MERGE MODE MIGRATE
  // TODO: MOD is a keyword that should not decay into an id. However, now that is does,
  // TODO: also "mod(a, 2)" kind of usage will be accepted. Incorrect use will anyway be
  // TODO: rejected by the server.
  MOD
  NAMES NEXT
  NO
  NOWAIT
  OF OFFSET OLD_PASSWORD OPEN ONLY
  PARTITIONS PASSWORD PREVIOUS
  QUERY QUICK
  RAISE RECURSIVE /*REINDEX*/ RELEASE /*RENAME*/ /*REPLACE*/ RESET RESTRICT ROLE ROLLBACK ROLLUP ROW REPEATABLE RESUME
  SAVEPOINT SELECT_OPTIONS_KW SEQUENCE SHARE SLAVE /*START*/ STATEMENT STATUS SERIALIZABLE SUSPEND SOFT
  TABLES TEMP TEMPTABLE TRANSACTION /*TRIGGER*/ TRIM TRIM_ARG
  /*TRUNCATE*/
  // TODO: UNSIGNED is a reserved word and should not automatically convert into an identifer.
  // TODO: However, if not here then rules such as CAST need to be modified.
  UNSIGNED UNCOMMITTED USER
  VALUE VIEW /*VIRTUAL*/
  WAIT
  /*WITH*/
  WORK
  XA
%endif
  .
%wildcard ANY.

// Define operator precedence early so that this is the first occurrence
// of the operator tokens in the grammer.  Keeping the operators together
// causes them to be assigned integer values that are close together,
// which keeps parser tables smaller.
//
// The token values assigned to these symbols is determined by the order
// in which lemon first sees them.  It must be the case that ISNULL/NOTNULL,
// NE/EQ, GT/LE, and GE/LT are separated by only a single value.  See
// the sqlite3ExprIfFalse() routine for additional information on this
// constraint.
//
%left OR.
%left AND.
%right NOT.
%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
%left GT LE LT GE.
%right ESCAPE.
%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left DIV MOD STAR SLASH REM.
%left CONCAT.
%left COLLATE.
%right BITNOT.

%ifdef MAXSCALE
// We need EQ in engine_opt up there, where CREATE is defined. However, as the
// value of a token is defined by the point the token is seen, EQ must not be
// used before the precedence is declared above where EQ and friends are
// declared in one go.
eq ::= EQ.
%endif

// And "ids" is an identifer-or-string.
//
%token_class ids  ID|STRING.

// The name of a column or table can be any of the following:
//
%type nm {Token}
nm(A) ::= id(X).         {A = X;}
nm(A) ::= STRING(X).     {A = X;}
nm(A) ::= JOIN_KW(X).    {A = X;}
nm(A) ::= START(X).      {A = X;}
nm(A) ::= TRUNCATE(X).   {A = X;}
nm(A) ::= BEGIN(X).      {A = X;}
nm(A) ::= REPLACE(X).    {A = X;}

// A typetoken is really one or more tokens that form a type name such
// as can be found after the column name in a CREATE TABLE statement.
// Multiple tokens are concatenated to form the value of the typetoken.
//
%type typetoken {Token}
type ::= .
type ::= typetoken(X).                   {sqlite3AddColumnType(pParse,&X);}
%ifdef MAXSCALE
enumnames ::= STRING.
enumnames ::= enumnames COMMA STRING.

type ::= ENUM LP enumnames RP.
type ::= SET LP enumnames RP.
%endif
typetoken(A) ::= typename(X).   {A = X;}
typetoken(A) ::= typename(X) LP signed RP(Y). {
  A.z = X.z;
  A.n = (int)(&Y.z[Y.n] - X.z);
}
typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). {
  A.z = X.z;
  A.n = (int)(&Y.z[Y.n] - X.z);
}
%type typename {Token}
typename(A) ::= ids(X).             {A = X;}
typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(int)(Y.z-X.z);}
signed ::= plus_num.
signed ::= minus_num.

// "carglist" is a list of additional constraints that come after the
// column name and column type in a CREATE TABLE statement.
//
%ifdef MAXSCALE
carglist ::= .
carglist ::= cconslist.

virtual_or_persistent ::= VIRTUAL.
virtual_or_persistent ::= PERSISTENT.

unique_key ::= .
unique_key ::= UNIQUE.
unique_key ::= UNIQUE KEY.

comment_string_opt ::= .
comment_string_opt ::= COMMENT STRING.

carglist ::= AS LP expr(X) RP virtual_or_persistent unique_key comment_string_opt. {
  sqlite3ExprDelete(pParse->db, X.pExpr);
}

cconslist ::= ccons.
cconslist ::= cconslist ccons.
%endif
%ifndef MAXSCALE
carglist ::= carglist ccons.
carglist ::= .
%endif
%ifndef MAXSCALE
ccons ::= CONSTRAINT nm(X).           {pParse->constraintName = X;}
%endif
ccons ::= DEFAULT term(X).            {sqlite3AddDefaultValue(pParse,&X);}
ccons ::= DEFAULT LP expr(X) RP.      {sqlite3AddDefaultValue(pParse,&X);}
ccons ::= DEFAULT PLUS term(X).       {sqlite3AddDefaultValue(pParse,&X);}
ccons ::= DEFAULT MINUS(A) term(X).      {
  ExprSpan v;
  v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, X.pExpr, 0, 0);
  v.zStart = A.z;
  v.zEnd = X.zEnd;
  sqlite3AddDefaultValue(pParse,&v);
}
ccons ::= DEFAULT id(X).              {
  ExprSpan v;
  spanExpr(&v, pParse, TK_STRING, &X);
  sqlite3AddDefaultValue(pParse,&v);
}
%ifdef MAXSCALE
ccons ::= DEFAULT id(X) LP RP. {
  ExprSpan v;
  spanExpr(&v, pParse, TK_STRING, &X);
  sqlite3AddDefaultValue(pParse,&v);
}
%endif

// In addition to the type name, we also care about the primary key and
// UNIQUE constraints.
//
%ifdef MAXSCALE
ccons ::= AUTOINCR.
%endif
ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R).    {sqlite3AddNotNull(pParse, R);}
%ifndef MAXSCALE
ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
                                 {sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
%endif
%ifdef MAXSCALE
// The addition of AUTOINCR above leads to conflicts if autoinc(I)
// follows onconf(R).
primary_opt ::= .
primary_opt ::= PRIMARY.

ccons ::= primary_opt KEY onconf(R).
                                 {sqlite3AddPrimaryKey(pParse,0,R,0,0);}
%endif
ccons ::= UNIQUE onconf(R).      {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);}
%ifndef MAXSCALE
ccons ::= CHECK LP expr(X) RP.   {sqlite3AddCheckConstraint(pParse,X.pExpr);}
// TODO: Following rule conflicts with "ccons ::= ON UPDATE ..." below.
ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
                                 {sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
%endif
ccons ::= defer_subclause(D).    {sqlite3DeferForeignKey(pParse,D);}
ccons ::= COLLATE ids(C).        {sqlite3AddCollateType(pParse, &C);}
%ifdef MAXSCALE
reference_option ::= RESTRICT.
reference_option ::= CASCADE.
reference_option ::= SET NULL.
reference_option ::= NO ACTION.
reference_option ::= CTIME_KW.

// TODO: ccons ::= [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
ccons ::= ON DELETE reference_option.
ccons ::= ON UPDATE reference_option.
ccons ::= ON UPDATE id LP RP.
%endif

// The optional AUTOINCREMENT keyword
%ifndef MAXSCALE
%type autoinc {int}
autoinc(X) ::= .          {X = 0;}
autoinc(X) ::= AUTOINCR.  {X = 1;}
%endif

// The next group of rules parses the arguments to a REFERENCES clause
// that determine if the referential integrity checking is deferred or
// or immediate and which determine what action to take if a ref-integ
// check fails.
//
%type refargs {int}
refargs(A) ::= .                  { A = OE_None*0x0101; /* EV: R-19803-45884 */}
refargs(A) ::= refargs(X) refarg(Y). { A = (X & ~Y.mask) | Y.value; }
%type refarg {struct {int value; int mask;}}
refarg(A) ::= MATCH nm.              { A.value = 0;     A.mask = 0x000000; }
refarg(A) ::= ON INSERT refact.      { A.value = 0;     A.mask = 0x000000; }
refarg(A) ::= ON DELETE refact(X).   { A.value = X;     A.mask = 0x0000ff; }
refarg(A) ::= ON UPDATE refact(X).   { A.value = X<<8;  A.mask = 0x00ff00; }
%type refact {int}
refact(A) ::= SET NULL.              { A = OE_SetNull;  /* EV: R-33326-45252 */}
refact(A) ::= SET DEFAULT.           { A = OE_SetDflt;  /* EV: R-33326-45252 */}
refact(A) ::= CASCADE.               { A = OE_Cascade;  /* EV: R-33326-45252 */}
refact(A) ::= RESTRICT.              { A = OE_Restrict; /* EV: R-33326-45252 */}
refact(A) ::= NO ACTION.             { A = OE_None;     /* EV: R-33326-45252 */}
%type defer_subclause {int}
defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt.     {A = 0;}
defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X).      {A = X;}
%type init_deferred_pred_opt {int}
init_deferred_pred_opt(A) ::= .                       {A = 0;}
init_deferred_pred_opt(A) ::= INITIALLY DEFERRED.     {A = 1;}
init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE.    {A = 0;}

conslist_opt(A) ::= .                         {A.n = 0; A.z = 0;}
conslist_opt(A) ::= COMMA(X) conslist.        {A = X;}
conslist ::= conslist tconscomma tcons.
conslist ::= tcons.
tconscomma ::= COMMA.            {pParse->constraintName.n = 0;}
tconscomma ::= .
tcons ::= CONSTRAINT nm(X).      {pParse->constraintName = X;}
%ifndef MAXSCALE
tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R).
                                 {sqlite3AddPrimaryKey(pParse,X,R,I,0);}
tcons ::= UNIQUE LP sortlist(X) RP onconf(R).
                                 {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);}
tcons ::= CHECK LP expr(E) RP onconf.
                                 {sqlite3AddCheckConstraint(pParse,E.pExpr);}
tcons ::= FOREIGN KEY LP eidlist(FA) RP
          REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
    sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
    sqlite3DeferForeignKey(pParse, D);
}
%endif
%type defer_subclause_opt {int}
defer_subclause_opt(A) ::= .                    {A = 0;}
defer_subclause_opt(A) ::= defer_subclause(X).  {A = X;}

// The following is a non-standard extension that allows us to declare the
// default behavior when there is a constraint conflict.
//
%type onconf {int}
%type orconf {int}
%ifdef MAXSCALE
onconf ::= .
orconf ::= .
%endif
%ifndef MAXSCALE
%type resolvetype {int}
onconf(A) ::= .                              {A = OE_Default;}
onconf(A) ::= ON CONFLICT resolvetype(X).    {A = X;}
orconf(A) ::= .                              {A = OE_Default;}
orconf(A) ::= OR resolvetype(X).             {A = X;}
resolvetype(A) ::= raisetype(X).             {A = X;}
resolvetype(A) ::= IGNORE.                   {A = OE_Ignore;}
resolvetype(A) ::= REPLACE.                  {A = OE_Replace;}
%endif

////////////////////////// The DROP TABLE /////////////////////////////////////
//
%ifdef MAXSCALE
table_or_tables ::= TABLE.
table_or_tables ::= TABLES.

cmd ::= DROP temp(T) table_or_tables ifexists(E) fullnames(X). {
  mxs_sqlite3DropTable(pParse, X, 0, E, T);
}
%endif
%ifndef MAXSCALE
cmd ::= DROP TABLE ifexists(E) fullname(X). {
  sqlite3DropTable(pParse, X, 0, E);
}
%endif
%type ifexists {int}
ifexists(A) ::= IF EXISTS.   {A = 1;}
ifexists(A) ::= .            {A = 0;}

///////////////////// The CREATE VIEW statement /////////////////////////////
//
%ifndef SQLITE_OMIT_VIEW
%ifdef MAXSCALE
%type algorithm {int}
algorithm(A) ::= UNDEFINED. {A=0;}
algorithm(A) ::= MERGE. {A=0;}
algorithm(A) ::= TEMPTABLE. {A=1;}

%type algorithm_opt {int}
algorithm_opt(A) ::= . {A=0;}
algorithm_opt(A) ::= ALGORITHM EQ algorithm(X). {A=X;}

cmd ::= createkw(X) algorithm_opt(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C)
          AS select(S). {
  mxs_sqlite3CreateView(pParse, &X, &Y, &Z, C, S, T, E);
  sqlite3SelectDelete(pParse->db, S);
}
%endif
%ifndef MAXSCALE
cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C)
          AS select(S). {
  sqlite3CreateView(pParse, &X, &Y, &Z, C, S, T, E);
}
%endif

%ifdef MAXSCALE
cmd ::= DROP VIEW ifexists(E) fullnames(X). {
  mxs_sqlite3DropTable(pParse, X, 1, E, 0);
}
%endif
%ifndef MAXSCALE
cmd ::= DROP VIEW ifexists(E) fullname(X). {
  sqlite3DropTable(pParse, X, 1, E);
}
%endif
%endif  SQLITE_OMIT_VIEW

//////////////////////// The SELECT statement /////////////////////////////////
//
%ifdef MAXSCALE
%type pselect {Select*}
%destructor pselect {sqlite3SelectDelete(pParse->db, $$);}

pselect(A) ::= LP pselect(X) RP. { A = X; }
pselect(A) ::= select(X). { A = X; }

cmd ::= pselect(X). {
%endif
%ifndef MAXSCALE
cmd ::= select(X).  {
%endif
  SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
#ifdef MAXSCALE
  mxs_sqlite3Select(pParse, X, &dest);
#else
  sqlite3Select(pParse, X, &dest);
#endif
  sqlite3SelectDelete(pParse->db, X);
}

%type select {Select*}
%destructor select {sqlite3SelectDelete(pParse->db, $$);}
%type selectnowith {Select*}
%destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);}
%ifdef MAXSCALE
%type selectnowithsuffix {Select*}
%destructor selectnowithsuffix {sqlite3SelectDelete(pParse->db, $$);}
%endif
%type oneselect {Select*}
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}

%include {
  /*
  ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
  ** all elements in the list.  And make sure list length does not exceed
  ** SQLITE_LIMIT_COMPOUND_SELECT.
  */
  static void parserDoubleLinkSelect(Parse *pParse, Select *p){
    if( p->pPrior ){
      Select *pNext = 0, *pLoop;
      int mxSelect, cnt = 0;
      for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
        pLoop->pNext = pNext;
        pLoop->selFlags |= SF_Compound;
      }
      if( (p->selFlags & SF_MultiValue)==0 && 
        (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
        cnt>mxSelect
      ){
        sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
      }
    }
  }
}

%ifdef MAXSCALE
select(A) ::= with(W) selectnowithsuffix(X). {
%endif
%ifndef MAXSCALE
select(A) ::= with(W) selectnowith(X). {
%endif
  Select *p = X;
  if( p ){
    p->pWith = W;
    parserDoubleLinkSelect(pParse, p);
  }else{
    sqlite3WithDelete(pParse->db, W);
  }
  A = p;
}

%ifdef MAXSCALE
selectnowithsuffix(A) ::= selectnowith(X). {A = X;}

for_something ::= FOR UPDATE.
for_something ::= FOR SHARE.
for_something ::= LOCK IN SHARE MODE.

selectnowithsuffix(A) ::= selectnowith(X) for_something. {
  A = X;
  maxscale_set_type_mask(QUERY_TYPE_WRITE);
}
%endif

selectnowith(A) ::= oneselect(X).                      {A = X;}
%ifndef SQLITE_OMIT_COMPOUND_SELECT
selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z).  {
  Select *pRhs = Z;
  Select *pLhs = X;
  if( pRhs && pRhs->pPrior ){
    SrcList *pFrom;
    Token x;
    x.n = 0;
    parserDoubleLinkSelect(pParse, pRhs);
    pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
#ifdef MAXSCALE
    pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0,0);
#else
    pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
#endif
  }
  if( pRhs ){
    pRhs->op = (u16)Y;
    pRhs->pPrior = pLhs;
    if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
    pRhs->selFlags &= ~SF_MultiValue;
    if( Y!=TK_ALL ) pParse->hasCompound = 1;
  }else{
    sqlite3SelectDelete(pParse->db, pLhs);
  }
  A = pRhs;
}
%type multiselect_op {int}
multiselect_op(A) ::= UNION(OP).             {A = @OP;}
multiselect_op(A) ::= UNION ALL.             {A = TK_ALL;}
multiselect_op(A) ::= EXCEPT|INTERSECT(OP).  {A = @OP;}
%endif SQLITE_OMIT_COMPOUND_SELECT
%ifdef MAXSCALE

wf_window_name ::= id.

wf_window_ref_opt ::= .
wf_window_ref_opt ::= id.

wf_window_spec ::= LP wf_window_ref_opt wf_partition_by_opt wf_order_by_opt wf_frame_opt RP.

wf_window_def ::= wf_window_name AS wf_window_spec.

wf_window_def_list ::= wf_window_def_list COMMA wf_window_def.
wf_window_def_list ::= wf_window_def.

wf_window ::= WINDOW wf_window_def_list.
wf_window ::= WINDOW LP RP.

wf_window_opt ::= .
wf_window_opt ::= wf_window.

oneselect(A) ::= SELECT select_options(D) selcollist(W) select_into_opt(I1) from(X) where_opt(Y)
                 groupby_opt(P) having_opt(Q) wf_window_opt orderby_opt(Z) limit_opt(L)
                 select_into_opt(I2). {
  if (!I1) {
    I1=I2;
  }
  A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset,I1);
}
oneselect(A) ::= SELECT select_options(D) selcollist(W) select_into(I). {
  A = sqlite3SelectNew(pParse,W,0,0,0,0,0,D,0,0,I);
}
oneselect(A) ::= SELECT select_options(D) selcollist(W) orderby_opt(Z) limit_opt(L). {
  A = sqlite3SelectNew(pParse,W,0,0,0,0,Z,D,L.pLimit,L.pOffset,0);
}
%endif
%ifndef MAXSCALE
oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
                 groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
  A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
#if SELECTTRACE_ENABLED
  /* Populate the Select.zSelName[] string that is used to help with
  ** query planner debugging, to differentiate between multiple Select
  ** objects in a complex query.
  **
  ** If the SELECT keyword is immediately followed by a C-style comment
  ** then extract the first few alphanumeric characters from within that
  ** comment to be the zSelName value.  Otherwise, the label is #N where
  ** is an integer that is incremented with each SELECT statement seen.
  */
  if( A!=0 ){
    const char *z = S.z+6;
    int i;
    sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "#%d",
                     ++pParse->nSelect);
    while( z[0]==' ' ) z++;
    if( z[0]=='/' && z[1]=='*' ){
      z += 2;
      while( z[0]==' ' ) z++;
      for(i=0; sqlite3Isalnum(z[i]); i++){}
      sqlite3_snprintf(sizeof(A->zSelName), A->zSelName, "%.*s", i, z);
    }
  }
#endif /* SELECTRACE_ENABLED */
}
%endif
oneselect(A) ::= values(X).    {A = X;}

%type values {Select*}
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
%ifdef MAXSCALE
value_or_values ::= VALUE.
value_or_values ::= VALUES.

values(A) ::= value_or_values LP exprlist(X) RP. {
  A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0,0);
}
%endif
%ifndef MAXSCALE
values(A) ::= VALUES LP nexprlist(X) RP. {
  A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
}
%endif
values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
  Select *pRight, *pLeft = X;
#ifdef MAXSCALE
  pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0,0);
#else
  pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
#endif
  if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
  if( pRight ){
    pRight->op = TK_ALL;
    pLeft = X;
    pRight->pPrior = pLeft;
    A = pRight;
  }else{
    A = pLeft;
  }
}

%ifdef MAXSCALE
%type variables {ExprList*}
%destructor variables {sqlite3ExprListDelete(pParse->db, $$);}

variables(A) ::= VARIABLE(X). {
      A = sqlite3ExprListAppend(pParse, NULL, 0);
      sqlite3ExprListSetName(pParse, A, &X, 1);
}
variables(A) ::= variables(X) COMMA VARIABLE(Y). {
      A = sqlite3ExprListAppend(pParse, X, 0);
      sqlite3ExprListSetName(pParse, A, &Y, 1);
}

%type select_into_opt {ExprList*}
%destructor select_into_opt {sqlite3ExprListDelete(pParse->db, $$);}
select_into_opt(A) ::= . {A = 0;}
select_into_opt(A) ::= select_into(X). {A = X;}

%type select_into {ExprList*}
%destructor select_into {sqlite3ExprListDelete(pParse->db, $$);}
select_into(A) ::= INTO variables(X). {A = X;}
// In order to allow us to distinguish between "INTO @var" and
// "INTO OUTFILE" or "INTO DUMPFILE", we give the expression list
// a name that cannot be a variable and look for that in
// maxscaleCollectInfoFromSelect().
select_into(A) ::= INTO DUMPFILE STRING. {
    static Token dumpfile = { ":DUMPFILE:", 10 };
    A = sqlite3ExprListAppend(pParse, 0, 0);
    sqlite3ExprListSetName(pParse, A, &dumpfile, 1);
}
select_into(A) ::= INTO OUTFILE STRING. {
    static Token outfile = { ":OUTFILE:", 9 };
    A = sqlite3ExprListAppend(pParse, 0, 0);
    sqlite3ExprListSetName(pParse, A, &outfile, 1);
}

%type select_options {int}
select_options(A) ::= . {A = 0;}
select_options(A) ::= select_options DISTINCT. {A = SF_Distinct;}
select_options(A) ::= select_options UNIQUE. {A = SF_Distinct;}
select_options(A) ::= select_options ALL. {A = SF_All;}
select_options(A) ::= select_options(X) HIGH_PRIORITY. {A = X;}
select_options(A) ::= select_options(X) SELECT_OPTIONS_KW. {A = X;}
select_options(A) ::= select_options(X) STRAIGHT_JOIN. {A = X;}
%endif
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
//
%type distinct {int}
%ifdef MAXSCALE
distinct(A) ::= UNIQUE.     {A = SF_Distinct;}
%endif
distinct(A) ::= DISTINCT.   {A = SF_Distinct;}
distinct(A) ::= ALL.        {A = SF_All;}
distinct(A) ::= .           {A = 0;}

// selcollist is a list of expressions that are to become the return
// values of the SELECT statement.  The "*" in statements like
// "SELECT * FROM ..." is encoded as a special expression with an
// opcode of TK_ASTERISK.
//
%type selcollist {ExprList*}
%destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);}
%type sclp {ExprList*}
%destructor sclp {sqlite3ExprListDelete(pParse->db, $$);}
sclp(A) ::= selcollist(X) COMMA.             {A = X;}
sclp(A) ::= .                                {A = 0;}
selcollist(A) ::= sclp(P) expr(X) as(Y).     {
   A = sqlite3ExprListAppend(pParse, P, X.pExpr);
   if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1);
   sqlite3ExprListSetSpan(pParse,A,&X);
}
selcollist(A) ::= sclp(P) STAR. {
  Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
  A = sqlite3ExprListAppend(pParse, P, p);
}
selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
  Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &Y);
  Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
  A = sqlite3ExprListAppend(pParse,P, pDot);
}
%ifdef MAXSCALE
next_or_previous(A) ::= NEXT(X). {A = X;}
next_or_previous(A) ::= PREVIOUS(X). {A = X;}

selcollist(A) ::= sclp(P) next_or_previous VALUE FOR nm(X) as(Y).     {
  Expr* pSeq = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  ExprList* pArgs = sqlite3ExprListAppend(pParse, NULL, pSeq);
  Token nextval = { "nextval", 7 };
  Expr* pFunc = sqlite3ExprFunction(pParse, pArgs, &nextval);
  if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1);
  A = sqlite3ExprListAppend(pParse, P, pFunc);
}
selcollist(A) ::= sclp(P) DEFAULT LP nm RP as. {
  A = P;
}
selcollist(A) ::= sclp(P) MATCH LP id(X) RP AGAINST LP expr(Y) RP. {
  // Could be a subselect as well, but we just don't know it at this point.
  sqlite3ExprDelete(pParse->db, Y.pExpr);
  Expr *p = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  maxscale_update_function_info("match", p);
  A = sqlite3ExprListAppend(pParse, P, p);
}
%endif


// An option "AS <id>" phrase that can follow one of the expressions that
// define the result set, or one of the tables in the FROM clause.
//
%type as {Token}
as(X) ::= AS nm(Y).    {X = Y;}
as(X) ::= ids(Y).      {X = Y;}
as(X) ::= .            {X.n = 0;}


%type seltablist {SrcList*}
%destructor seltablist {sqlite3SrcListDelete(pParse->db, $$);}
%type stl_prefix {SrcList*}
%destructor stl_prefix {sqlite3SrcListDelete(pParse->db, $$);}
%type from {SrcList*}
%destructor from {sqlite3SrcListDelete(pParse->db, $$);}

// A complete FROM clause.
//
%ifndef MAXSCALE
from(A) ::= .                {A = sqlite3DbMallocZero(pParse->db, sizeof(*A));}
%endif
from(A) ::= FROM seltablist(X). {
  A = X;
  sqlite3SrcListShiftJoinType(A);
}
%endif

// "seltablist" is a "Select Table List" - the content of the FROM clause
// in a SELECT statement.  "stl_prefix" is a prefix of this list.
//
stl_prefix(A) ::= seltablist(X) joinop(Y).    {
   A = X;
   if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u16)Y;
}
stl_prefix(A) ::= .                           {A = 0;}
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I)
                  on_opt(N) using_opt(U). {
  A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
  sqlite3SrcListIndexedBy(pParse, A, &I);
}
%ifdef MAXSCALE
// as(X) above cannot be used, since it is used in other contexts as well.
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) EQ nm(Z) indexed_opt(I)
                  on_opt(N) using_opt(U). {
  A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
  sqlite3SrcListIndexedBy(pParse, A, &I);
}
%endif
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
                  on_opt(N) using_opt(U). {
  A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
  sqlite3SrcListFuncArgs(pParse, A, E);
}
%ifndef SQLITE_OMIT_SUBQUERY
  seltablist(A) ::= stl_prefix(X) LP select(S) RP
                    as(Z) on_opt(N) using_opt(U). {
    A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U);
  }
  seltablist(A) ::= stl_prefix(X) LP seltablist(F) RP
                    as(Z) on_opt(N) using_opt(U). {
    if( X==0 && Z.n==0 && N==0 && U==0 ){
      A = F;
    }else if( F->nSrc==1 ){
      A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,0,N,U);
      if( A ){
        struct SrcList_item *pNew = &A->a[A->nSrc-1];
        struct SrcList_item *pOld = F->a;
        pNew->zName = pOld->zName;
        pNew->zDatabase = pOld->zDatabase;
        pNew->pSelect = pOld->pSelect;
        pOld->zName = pOld->zDatabase = 0;
        pOld->pSelect = 0;
      }
      sqlite3SrcListDelete(pParse->db, F);
    }else{
      Select *pSubquery;
      sqlite3SrcListShiftJoinType(F);
#ifdef MAXSCALE
      pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0,0,0);
#else
      pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0,0);
#endif
      A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,pSubquery,N,U);
    }
  }
%endif  SQLITE_OMIT_SUBQUERY

%type dbnm {Token}
dbnm(A) ::= .          {A.z=0; A.n=0;}
dbnm(A) ::= DOT nm(X). {A = X;}

%type fullname {SrcList*}
%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);}
fullname(A) ::= nm(X) dbnm(Y).  {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);}

%ifdef MAXSCALE
%type fullnames {SrcList*}
%destructor fullnames {sqlite3SrcListDelete(pParse->db, $$);}
fullnames(A) ::= fullname(X). {A = X;}
fullnames(A) ::= fullnames(W) COMMA nm(X) dbnm(Y). {
    A = sqlite3SrcListAppend(pParse->db, W, &X, &Y);
}
%endif

%type joinop {int}
joinop(X) ::= COMMA|JOIN.              { X = JT_INNER; }
joinop(X) ::= JOIN_KW(A) JOIN.         { X = sqlite3JoinType(pParse,&A,0,0); }
joinop(X) ::= JOIN_KW(A) nm(B) JOIN.   { X = sqlite3JoinType(pParse,&A,&B,0); }
joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
                                       { X = sqlite3JoinType(pParse,&A,&B,&C); }
%ifdef MAXSCALE
joinop(X) ::= join_opt STRAIGHT_JOIN.  { X = JT_INNER; }
%endif

%type on_opt {Expr*}
%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
on_opt(N) ::= ON expr(E).   {N = E.pExpr;}
on_opt(N) ::= .             {N = 0;}

// Note that this block abuses the Token type just a little. If there is
// no "INDEXED BY" clause, the returned token is empty (z==0 && n==0). If
// there is an INDEXED BY clause, then the token is populated as per normal,
// with z pointing to the token data and n containing the number of bytes
// in the token.
//
// If there is a "NOT INDEXED" clause, then (z==0 && n==1), which is 
// normally illegal. The sqlite3SrcListIndexedBy() function 
// recognizes and interprets this as a special case.
//
%type indexed_opt {Token}
indexed_opt(A) ::= .                 {A.z=0; A.n=0;}
%ifndef MAXSCALE
indexed_opt(A) ::= INDEXED BY nm(X). {A = X;}
indexed_opt(A) ::= NOT INDEXED.      {A.z=0; A.n=1;}
%endif
%ifdef MAXSCALE
uif ::= USE|IGNORE|FORCE.

jog ::= JOIN|ORDER BY|GROUP BY.

for_jog ::= .
for_jog ::= FOR jog.

index_name ::= id.
index_name ::= PRIMARY.

index_list ::= index_name.
index_list ::= index_list COMMA index_name.

index_hint ::= uif index_or_key for_jog LP index_list RP.

index_hint_list ::= index_hint.
// TODO: index_hint_list ::= index_hint_list COMMA index_hint.
// TODO: Causes parsing conflict.

indexed_opt(A) ::= index_hint_list. {A.z=0; A.n=0;}
%endif

%type using_opt {IdList*}
%destructor using_opt {sqlite3IdListDelete(pParse->db, $$);}
using_opt(U) ::= USING LP idlist(L) RP.  {U = L;}
using_opt(U) ::= .                        {U = 0;}


%type orderby_opt {ExprList*}
%destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);}

// the sortlist non-terminal stores a list of expression where each
// expression is optionally followed by ASC or DESC to indicate the
// sort order.
//
%type sortlist {ExprList*}
%destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);}

orderby_opt(A) ::= .                          {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {
  A = sqlite3ExprListAppend(pParse,X,Y.pExpr);
  sqlite3ExprListSetSortOrder(A,Z);
}
sortlist(A) ::= expr(Y) sortorder(Z). {
  A = sqlite3ExprListAppend(pParse,0,Y.pExpr);
  sqlite3ExprListSetSortOrder(A,Z);
}

%type sortorder {int}

sortorder(A) ::= ASC.           {A = SQLITE_SO_ASC;}
sortorder(A) ::= DESC.          {A = SQLITE_SO_DESC;}
sortorder(A) ::= .              {A = SQLITE_SO_UNDEFINED;}

%type groupby_opt {ExprList*}
%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
groupby_opt(A) ::= .                      {A = 0;}
%ifndef MAXSCALE
groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
%endif
%ifdef MAXSCALE
with_rollup ::= WITH ROLLUP.
with_rollup ::= .

groupby_opt(A) ::= GROUP BY nexprlist(X) sortorder with_rollup. {A = X;}
%endif

%type having_opt {Expr*}
%destructor having_opt {sqlite3ExprDelete(pParse->db, $$);}
having_opt(A) ::= .                {A = 0;}
having_opt(A) ::= HAVING expr(X).  {A = X.pExpr;}

%type limit_opt {struct LimitVal}

// The destructor for limit_opt will never fire in the current grammar.
// The limit_opt non-terminal only occurs at the end of a single production
// rule for SELECT statements.  As soon as the rule that create the 
// limit_opt non-terminal reduces, the SELECT statement rule will also
// reduce.  So there is never a limit_opt non-terminal on the stack 
// except as a transient.  So there is never anything to destroy.
//
//%destructor limit_opt {
//  sqlite3ExprDelete(pParse->db, $$.pLimit);
//  sqlite3ExprDelete(pParse->db, $$.pOffset);
//}
limit_opt(A) ::= .                    {A.pLimit = 0; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X).       {A.pLimit = X.pExpr; A.pOffset = 0;}
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). 
                                      {A.pLimit = X.pExpr; A.pOffset = Y.pExpr;}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). 
                                      {A.pOffset = X.pExpr; A.pLimit = Y.pExpr;}

/////////////////////////// The DELETE statement /////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
%ifdef MAXSCALE
low_priority_quick_ignore_opt ::= .
low_priority_quick_ignore_opt ::= LOW_PRIORITY.
low_priority_quick_ignore_opt ::= QUICK.
low_priority_quick_ignore_opt ::= IGNORE.

cmd ::= with(C) DELETE low_priority_quick_ignore_opt FROM fullname(X) indexed_opt(I) where_opt(W) 
        orderby_opt(O) limit_opt(L). {
%endif
%ifndef MAXSCALE
cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W) 
        orderby_opt(O) limit_opt(L). {
%endif
  sqlite3WithPush(pParse, C, 1);
  sqlite3SrcListIndexedBy(pParse, X, &I);
#ifdef MAXSCALE
  Token token;
  ExprSpan limit;
  if (O && !L.pLimit) {
    L.pLimit = maxscale_create_pseudo_limit(pParse, &token, &limit);
    sqlite3ExprDelete(pParse->db, L.pOffset);
    L.pOffset = 0;
  }
  W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
  mxs_sqlite3DeleteFrom(pParse,X,W,0);
#else
  W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
  sqlite3DeleteFrom(pParse,X,W);
#endif
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
  sqlite3WithPush(pParse, C, 1);
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3DeleteFrom(pParse,X,W);
}
%endif

%type where_opt {Expr*}
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}

where_opt(A) ::= .                    {A = 0;}
where_opt(A) ::= WHERE expr(X).       {A = X.pExpr;}

%ifdef MAXSCALE
%type table_factor {SrcList*}
%destructor table_factor {sqlite3SrcListDelete(pParse->db, $$);}

table_factor(A) ::= nm(X). {
  A = sqlite3SrcListAppend(pParse->db, 0, &X, 0);
}

table_factor(A) ::= nm(X) as_opt id(Y). {
  A = sqlite3SrcListAppendFromTerm(pParse, 0, &X, 0, &Y, 0, 0, 0);
}

table_factor(A) ::= nm(X) DOT nm(Y). {
  A = sqlite3SrcListAppend(pParse->db, 0, &X, &Y);
}

table_factor(A) ::= nm(X) DOT nm(Y) as_opt id(Z). {
  A = sqlite3SrcListAppendFromTerm(pParse, 0, &X, &Y, &Z, 0, 0, 0);
}

table_factor(A) ::= LP oneselect(S) RP as_opt id(Z). {
  A = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &Z, S, 0, 0);
}

%type table_reference {SrcList*}
%destructor table_reference {sqlite3SrcListDelete(pParse->db, $$);}

table_reference(A) ::= table_factor(X). {
  A = X;
}

table_reference(A) ::= join_table(X). {
  A = X;
}

%type join_table {SrcList*}
%destructor join_table {sqlite3SrcListDelete(pParse->db, $$);}

join_opt ::= .
join_opt ::= JOIN_KW.

%type join_condition {ExprSpan}
%destructor join_condition {sqlite3ExprDelete(pParse->db, $$.pExpr);}

join_table(A) ::= table_reference(X) join_opt JOIN table_reference(Y) join_condition(Z). {
  Y->a[Y->nSrc - 1].pOn = Z.pExpr;
  A = sqlite3SrcListCat(pParse->db, X, Y);
}

join_condition(A) ::= ON expr(X). {
  A = X;
}

%type escaped_table_reference {SrcList*}
%destructor escaped_table_reference {sqlite3SrcListDelete(pParse->db, $$);}

escaped_table_reference(A) ::= table_reference(X). {
  A = X;
}

%type table_references {SrcList*}
%destructor table_references {sqlite3SrcListDelete(pParse->db, $$);}

table_references(A) ::= escaped_table_reference(X). {
  A = X;
}

table_references(A) ::= table_references(X) COMMA escaped_table_reference(Y). {
  A = sqlite3SrcListCat(pParse->db, X, Y);
}

%type tbl_name {SrcList*}
%destructor tbl_name {sqlite3SrcListDelete(pParse->db, $$);}

tbl_name(A) ::= nm(X). { A = sqlite3SrcListAppend(pParse->db,0,&X,0); }
tbl_name(A) ::= nm(X) DOT STAR. { A = sqlite3SrcListAppend(pParse->db,0,&X,0); }
tbl_name(A) ::= nm(X) DOT nm(Y). { A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); }
tbl_name(A) ::= nm(X) DOT nm(Y) DOT STAR. { A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); }

%type tbl_names {SrcList*}
%destructor tbl_names {sqlite3SrcListDelete(pParse->db, $$);}

tbl_names(A) ::= tbl_name(X). { A = X; }
tbl_names(A) ::= tbl_names(X) COMMA tbl_name(Y). {
  A = sqlite3SrcListCat(pParse->db, X, Y);
}

cmd ::= with(C) DELETE low_priority_quick_ignore_opt
            tbl_names(X)
            FROM table_references(U)
            where_opt(W). {
  sqlite3WithPush(pParse, C, 1);
  mxs_sqlite3DeleteFrom(pParse, X, W, U);
}

cmd ::= with(C) DELETE low_priority_quick_ignore_opt
            FROM tbl_names(X)
            USING table_references(U)
            where_opt(W). {
  sqlite3WithPush(pParse, C, 1);
  mxs_sqlite3DeleteFrom(pParse, X, W, U);
}

%endif

////////////////////////// The UPDATE command ////////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
%ifdef MAXSCALE
low_priority_or_ignore_opt ::= .
low_priority_or_ignore_opt ::= low_priority_or_ignore_opt IGNORE.
low_priority_or_ignore_opt ::= low_priority_or_ignore_opt LOW_PRIORITY.

%type mxs_setlist {ExprList*}
%destructor mxs_setlist {sqlite3ExprListDelete(pParse->db, $$);}

mxs_setlist(A) ::= col_name(X) EQ expr(Y). {
  Expr* pEq = sqlite3PExpr(pParse, TK_EQ, X.pExpr, Y.pExpr, 0);
  A = sqlite3ExprListAppend(pParse, 0, pEq);
}

mxs_setlist(A) ::= mxs_setlist(Z) COMMA col_name(X) EQ expr(Y). {
  Expr* pEq = sqlite3PExpr(pParse, TK_EQ, X.pExpr, Y.pExpr, 0);
  A = sqlite3ExprListAppend(pParse, Z, pEq);
}

cmd ::= with(C) UPDATE low_priority_or_ignore_opt orconf(R) table_references(X) indexed_opt(I) SET mxs_setlist(Y)
        where_opt(W) orderby_opt(O) limit_opt(L).  {
%endif
%ifndef MAXSCALE
cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
        where_opt(W) orderby_opt(O) limit_opt(L).  {
%endif
  sqlite3WithPush(pParse, C, 1);
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
#ifdef MAXSCALE
  Token token;
  ExprSpan limit;
  if (O && !L.pLimit) {
    L.pLimit = maxscale_create_pseudo_limit(pParse, &token, &limit);
    sqlite3ExprDelete(pParse->db, L.pOffset);
    L.pOffset = 0;
  }

  W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
  mxs_sqlite3Update(pParse,X,Y,W,R);
#else
  W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
  sqlite3Update(pParse,X,Y,W,R);
#endif
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
        where_opt(W).  {
  sqlite3WithPush(pParse, C, 1);
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
  sqlite3Update(pParse,X,Y,W,R);
}
%endif

%type setlist {ExprList*}
%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}

setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). {
  A = sqlite3ExprListAppend(pParse, Z, Y.pExpr);
  sqlite3ExprListSetName(pParse, A, &X, 1);
}
setlist(A) ::= nm(X) EQ expr(Y). {
  A = sqlite3ExprListAppend(pParse, 0, Y.pExpr);
  sqlite3ExprListSetName(pParse, A, &X, 1);
}

////////////////////////// The INSERT command /////////////////////////////////
//
cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) select(S). {
  sqlite3WithPush(pParse, W, 1);
#ifdef MAXSCALE
  mxs_sqlite3Insert(pParse, X, S, F, R, 0);
#else
  sqlite3Insert(pParse, X, S, F, R);
#endif
}
cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES.
{
  sqlite3WithPush(pParse, W, 1);
#ifdef MAXSCALE
  mxs_sqlite3Insert(pParse, X, 0, F, R, 0);
#else
  sqlite3Insert(pParse, X, 0, F, R);
#endif
}

%ifdef MAXSCALE
cmd ::= with(W) insert_cmd(R) fullname(X) idlist_opt(F) DEFAULT VALUES.
{
  sqlite3WithPush(pParse, W, 1);
  mxs_sqlite3Insert(pParse, X, 0, F, R, 0);
}

cmd ::= with(W) insert_cmd(R) fullname(X) idlist_opt(F) select(S). {
  sqlite3WithPush(pParse, W, 1);
  mxs_sqlite3Insert(pParse, X, S, F, R, 0);
}

%type col_name {ExprSpan}
%destructor col_name {sqlite3ExprDelete(pParse->db, $$.pExpr);}

col_name(A) ::= nm(X). {
    spanExpr(&A, pParse, TK_ID, &X);
}
col_name(A) ::= nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&A,&X,&Y);
}
col_name(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z);
  Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
  spanSet(&A,&X,&Z);
}

%type col_name_value {ExprSpan}
%destructor col_name_value {sqlite3ExprDelete(pParse->db, $$.pExpr);}

col_name_value(A) ::= col_name(X) EQ expr(Y). {
  spanBinaryExpr(&A,pParse,TK_EQ,&X,&Y);
}

%type col_name_values {ExprList*}
%destructor col_name_values {sqlite3ExprListDelete(pParse->db, $$);}

col_name_values(A) ::= col_name_value(X). {
  A = sqlite3ExprListAppend(pParse, 0, X.pExpr);
}
col_name_values(A) ::= col_name_values(X) COMMA col_name_value(Y). {
  A = sqlite3ExprListAppend(pParse, X, Y.pExpr);
}

cmd ::= with(W) insert_cmd(R) fullname(X) SET col_name_values(Z).
{
  sqlite3WithPush(pParse, W, 1);
  mxs_sqlite3Insert(pParse, X, 0, 0, R, Z);
}

cmd ::= with(W) insert_cmd(R) INTO fullname(X) SET col_name_values(Z).
{
  sqlite3WithPush(pParse, W, 1);
  mxs_sqlite3Insert(pParse, X, 0, 0, R, Z);
}
%endif

%type insert_cmd {int}
%ifdef MAXSCALE
priority_opt ::= .
priority_opt ::= LOW_PRIORITY.
priority_opt ::= DELAYED.
priority_opt ::= HIGH_PRIORITY.

ignore_opt ::= .
ignore_opt ::= IGNORE.

insert_cmd(A) ::= INSERT priority_opt ignore_opt orconf(R).   {A = R;}
%endif
%ifndef MAXSCALE
insert_cmd(A) ::= INSERT orconf(R).   {A = R;}
%endif
insert_cmd(A) ::= REPLACE.            {A = OE_Replace;}
%type idlist_opt {IdList*}
%destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);}

%type idlist {IdList*}
%destructor idlist {sqlite3IdListDelete(pParse->db, $$);}

idlist_opt(A) ::= .                       {A = 0;}
idlist_opt(A) ::= LP idlist(X) RP.    {A = X;}
idlist(A) ::= idlist(X) COMMA nm(Y).
    {A = sqlite3IdListAppend(pParse->db,X,&Y);}
idlist(A) ::= nm(Y).
    {A = sqlite3IdListAppend(pParse->db,0,&Y);}

/////////////////////////// Expression Processing /////////////////////////////
//

%type expr {ExprSpan}
%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);}
%type term {ExprSpan}
%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);}

%include {
  /* This is a utility routine used to set the ExprSpan.zStart and
  ** ExprSpan.zEnd values of pOut so that the span covers the complete
  ** range of text beginning with pStart and going to the end of pEnd.
  */
  static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){
    pOut->zStart = pStart->z;
    pOut->zEnd = &pEnd->z[pEnd->n];
  }

  /* Construct a new Expr object from a single identifier.  Use the
  ** new Expr to populate pOut.  Set the span of pOut to be the identifier
  ** that created the expression.
  */
  static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){
    pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, pValue);
    pOut->zStart = pValue->z;
    pOut->zEnd = &pValue->z[pValue->n];
  }
}

expr(A) ::= term(X).             {A = X;}
%ifndef MAXSCALE
expr(A) ::= LP(B) expr(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);}
%endif
%ifdef MAXSCALE
%type exprs {ExprSpan}
%destructor exprs {sqlite3ExprDelete(pParse->db, $$.pExpr);}
exprs(A) ::= expr(X). { A = X; }
exprs(A) ::= exprs(X) COMMA(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= LP(B) exprs(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);}
term(A) ::= DEFAULT(X).          {spanExpr(&A, pParse, @X, &X);}
%endif
term(A) ::= NULL(X).             {spanExpr(&A, pParse, @X, &X);}
expr(A) ::= id(X).               {spanExpr(&A, pParse, TK_ID, &X);}
// This is for "[UN]SIGNED INTEGER" and alikes. We claim it is
// TK_UNSIGNED and not TK_ID as in that case it appears as if
// the field "INTEGER" would be referred to.
expr(A) ::= UNSIGNED(X) id.      {spanExpr(&A, pParse, TK_UNSIGNED, &X);}
expr(A) ::= nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&A,&X,&Y);
}
expr(A) ::= DOT nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&A,&X,&Y);
}
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z);
  Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
  spanSet(&A,&X,&Z);
}
term(A) ::= INTEGER|FLOAT|BLOB(X).  {spanExpr(&A, pParse, @X, &X);}
term(A) ::= STRING(X).              {spanExpr(&A, pParse, @X, &X);}
term(A) ::= CHARSET_NAME_KW(X) STRING(Y). {spanExpr(&A, pParse, @X, &Y);}
term(A) ::= CHARSET_NAME_KW(X) BLOB(Y). {spanExpr(&A, pParse, @X, &Y);}
expr(A) ::= VARIABLE(X).     {
  if( X.n>=2 && X.z[0]=='#' && sqlite3Isdigit(X.z[1]) ){
    /* When doing a nested parse, one can include terms in an expression
    ** that look like this:   #1 #2 ...  These terms refer to registers
    ** in the virtual machine.  #N is the N-th register. */
    if( pParse->nested==0 ){
      sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &X);
      A.pExpr = 0;
    }else{
      A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &X);
      if( A.pExpr ) sqlite3GetInt32(&X.z[1], &A.pExpr->iTable);
    }
  }else{
    spanExpr(&A, pParse, TK_VARIABLE, &X);
    sqlite3ExprAssignVarNumber(pParse, A.pExpr);
  }
  spanSet(&A, &X, &X);
}
%ifdef MAXSCALE
expr(A) ::= CHARSET_NAME_KW(X) INTEGER(Y). {
  // The sole purpose of this is to interpret something like '_utf8mb4 0xD091D092D093'
  // as a string. It does not matter that any identifier followed by an integer will
  // be interpreted as a string, as invalid usage will be caught by the server.
  A.pExpr = sqlite3PExpr(pParse, TK_STRING, 0, 0, &Y);
  spanSet(&A, &X, &Y);
}
expr(A) ::= VARIABLE(X) variable_tail(Y).     {
  // As we won't be executing any queries, we do not need to do
  // the things that are done above.
  ExprSpan v;
  v.pExpr = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, &X);
  spanSet(&v, &X, &X);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, v.pExpr, Y.pExpr, 0);
  A.zStart = v.zStart;
  A.zEnd = Y.zEnd;
}
%endif
expr(A) ::= expr(E) COLLATE ids(C). {
  A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1);
  A.zStart = E.zStart;
  A.zEnd = &C.z[C.n];
}
%ifndef SQLITE_OMIT_CAST
expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
  A.pExpr = sqlite3PExpr(pParse, TK_CAST, E.pExpr, 0, &T);
  spanSet(&A,&X,&Y);
}
%endif  SQLITE_OMIT_CAST
%ifdef MAXSCALE

%type group_concat_colname {ExprSpan}
%destructor group_concat_colname {sqlite3ExprDelete(pParse->db, $$.pExpr);}

group_concat_colname(A) ::= nm(X). {
  spanExpr(&A, pParse, TK_ID, &X);
}

group_concat_colname(A) ::= nm(X) DOT nm(Y). {
  Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&A,&X,&Y);
}

%type group_concat_colnames {ExprList*}
%destructor group_concat_colnames {sqlite3ExprListDelete(pParse->db, $$);}

group_concat_colnames(A) ::= group_concat_colname(Y). {
  A = sqlite3ExprListAppend(pParse, 0, Y.pExpr);
}

group_concat_colnames(A) ::= group_concat_colnames(X) COMMA group_concat_colname(Y). {
  A = sqlite3ExprListAppend(pParse, X, Y.pExpr);
}

%type group_concat_colnames_opt {ExprList*}
%destructor group_concat_colnames_opt {sqlite3ExprListDelete(pParse->db, $$);}

group_concat_colnames_opt(A) ::= . { A = NULL; }
group_concat_colnames_opt(A) ::= COMMA group_concat_colnames(X). { A = X; }

%type group_concat_order_by {ExprList*}
%destructor group_concat_order_by {sqlite3ExprListDelete(pParse->db, $$);}

group_concat_order_by(A) ::= ORDER BY INTEGER sortorder group_concat_colnames_opt(X). {
  A = X;
}
group_concat_order_by(A) ::= ORDER BY col_name(X) sortorder group_concat_colnames_opt(Y). {
  A = sqlite3ExprListAppend(pParse, Y, X.pExpr);
}
// TODO: The following causes conflicts.
//group_concat_order_by ::= ORDER BY expr(X) sortorder group_concat_colnames_opt. {
//  sqlite3ExprDelete(pParse->db, X.pExpr);
//}

group_concat_separator ::= SEPARATOR STRING.

%type group_concat_tail {ExprList*}
%destructor group_concat_tail {sqlite3ExprListDelete(pParse->db, $$);}

group_concat_tail(A) ::= group_concat_order_by(X). { A = X; }
group_concat_tail(A) ::= group_concat_separator. { A = NULL; }
group_concat_tail(A) ::= group_concat_order_by(X) group_concat_separator. { A = X; }

convert_tail ::= USING id.

// Since we don't use the arguments for anything, any function can have these
// as trailing arguments. It's ok because if used incorrectly, the server will
// reject the statement

%type func_arg_tail_opt {ExprList*}
%destructor func_arg_tail_opt {sqlite3ExprListDelete(pParse->db, $$);}

func_arg_tail_opt(A) ::= . { A = NULL; }
func_arg_tail_opt(A) ::= group_concat_tail(X). { A = X; }
func_arg_tail_opt(A) ::= convert_tail. { A = NULL; }

wf_partition_by ::= PARTITION BY nexprlist(X). {
  sqlite3ExprListDelete(pParse->db, X);
}

wf_partition_by_opt ::= .
wf_partition_by_opt ::= wf_partition_by.

wf_order_by ::= ORDER BY nexprlist(X) sortorder. {
  sqlite3ExprListDelete(pParse->db, X);
}

wf_order_by_opt ::= .
wf_order_by_opt ::= wf_order_by.

wf_frame_units ::= RANGE.
wf_frame_units ::= ROWS.

wf_frame_start ::= UNBOUNDED PRECEDING.
wf_frame_start ::= CURRENT ROW.
wf_frame_start ::= term(X) PRECEDING. {
    sqlite3ExprDelete(pParse->db, X.pExpr);
}

wf_frame_bound ::= wf_frame_start.
wf_frame_bound ::= UNBOUNDED FOLLOWING.
wf_frame_bound ::= term(X) FOLLOWING. {
    sqlite3ExprDelete(pParse->db, X.pExpr);
}

wf_frame_extent ::= wf_frame_start.
wf_frame_extent ::= BETWEEN wf_frame_bound AND wf_frame_bound.

wf_frame_exclusion_opt ::= .
wf_frame_exclusion_opt ::= EXCLUDE CURRENT ROW.
wf_frame_exclusion_opt ::= EXCLUDE GROUP.
wf_frame_exclusion_opt ::= EXCLUDE TIES.
wf_frame_exclusion_opt ::= EXCLUDE NO OTHERS.

wf_frame_opt ::= .
wf_frame_opt ::= wf_frame_units wf_frame_extent wf_frame_exclusion_opt .

wf ::= OVER LP wf_window_ref_opt wf_partition_by_opt wf_order_by_opt wf_frame_opt RP.
wf ::= OVER id.

wf_opt ::= .
wf_opt ::= wf.

expr(A) ::= id(X) LP distinct(D) exprlist(Y) func_arg_tail_opt(Z) RP(E) wf_opt. {
  // We just append Z on Y as we are only interested in what columns
  // the function used.
  Y = sqlite3ExprListAppendList(pParse, Y, Z);
%endif
%ifndef MAXSCALE
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
%endif
  if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
  }
  A.pExpr = sqlite3ExprFunction(pParse, Y, &X);
  spanSet(&A,&X,&E);
  if( D==SF_Distinct && A.pExpr ){
    A.pExpr->flags |= EP_Distinct;
  }
}
%ifdef MAXSCALE
expr(A) ::= nm DOT nm(X) LP distinct(D) exprlist(Y) func_arg_tail_opt(Z) RP(E) wf_opt. {
  // We just append Z on Y as we are only interested in what columns
  // the function used.
  Y = sqlite3ExprListAppendList(pParse, Y, Z);
  if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
  }
  A.pExpr = sqlite3ExprFunction(pParse, Y, &X);
  spanSet(&A,&X,&E);
  if( D==SF_Distinct && A.pExpr ){
    A.pExpr->flags |= EP_Distinct;
  }
}

keyword_as_function(A) ::= JOIN_KW(X). {A = X;}
keyword_as_function(A) ::= INSERT(X). {A = X;}
keyword_as_function(A) ::= REPLACE(X). {A = X;}

expr(A) ::= keyword_as_function(X) LP distinct(D) exprlist(Y) RP(E). {
  if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
    sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
  }
  A.pExpr = sqlite3ExprFunction(pParse, Y, &X);
  spanSet(&A,&X,&E);
  if( D==SF_Distinct && A.pExpr ){
    A.pExpr->flags |= EP_Distinct;
  }
}


%type trim_args {ExprSpan}
%destructor trim_args {sqlite3ExprDelete(pParse->db, $$.pExpr);}
trim_args(A) ::= TRIM_ARG term FROM expr(X). { A = X; }
trim_args(A) ::= TRIM_ARG FROM expr(X). { A = X; }
trim_args(A) ::= term FROM expr(X). { A = X; }
trim_args(A) ::= expr(X). { A = X; }

expr(A) ::= TRIM(X) LP trim_args(Y) RP(Z). {
  ExprList* pArgs = sqlite3ExprListAppend(pParse, NULL, Y.pExpr);
  A.pExpr = sqlite3ExprFunction(pParse, pArgs, &X);
  spanSet(&A, &X, &Z);
}
%endif
expr(A) ::= id(X) LP STAR RP(E) wf_opt. {
  A.pExpr = sqlite3ExprFunction(pParse, 0, &X);
  spanSet(&A,&X,&E);
}
term(A) ::= CTIME_KW(OP). {
  A.pExpr = sqlite3ExprFunction(pParse, 0, &OP);
  spanSet(&A, &OP, &OP);
}

%include {
  /* This routine constructs a binary expression node out of two ExprSpan
  ** objects and uses the result to populate a new ExprSpan object.
  */
  static void spanBinaryExpr(
    ExprSpan *pOut,     /* Write the result here */
    Parse *pParse,      /* The parsing context.  Errors accumulate here */
    int op,             /* The binary operation */
    ExprSpan *pLeft,    /* The left operand */
    ExprSpan *pRight    /* The right operand */
  ){
    pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
    pOut->zStart = pLeft->zStart;
    pOut->zEnd = pRight->zEnd;
  }

  /* If doNot is true, then add a TK_NOT Expr-node wrapper around the
  ** outside of *ppExpr.
  */
  static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){
    if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0);
  }
}

expr(A) ::= expr(X) AND(OP) expr(Y).    {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= expr(X) OR(OP) expr(Y).     {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y).
                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= expr(X) EQ|NE(OP) expr(Y).  {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).
                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
%ifdef MAXSCALE
expr(A) ::= INTERVAL expr(X) id. {
  // Here we could check that id is one of MICROSECOND, SECOND, MINUTE
  // HOUR, DAY, WEEK, etc.
  A=X; // We simply ignore 'INTERVAL'
}
%endif
expr(A) ::= expr(X) DIV|MOD|STAR|SLASH|REM(OP) expr(Y).
                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
expr(A) ::= expr(X) CONCAT(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
%type likeop {struct LikeOp}
likeop(A) ::= LIKE_KW|MATCH(X).     {A.eOperator = X; A.bNot = 0;}
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;}
expr(A) ::= expr(X) likeop(OP) expr(Y).  [LIKE_KW]  {
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
  A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
  exprNot(pParse, OP.bNot, &A.pExpr);
  A.zStart = X.zStart;
  A.zEnd = Y.zEnd;
  if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
}
expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E).  [LIKE_KW]  {
  ExprList *pList;
  pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, E.pExpr);
  A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
  exprNot(pParse, OP.bNot, &A.pExpr);
  A.zStart = X.zStart;
  A.zEnd = E.zEnd;
  if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
}

%include {
  /* Construct an expression node for a unary postfix operator
  */
  static void spanUnaryPostfix(
    ExprSpan *pOut,        /* Write the new expression node here */
    Parse *pParse,         /* Parsing context to record errors */
    int op,                /* The operator */
    ExprSpan *pOperand,    /* The operand */
    Token *pPostOp         /* The operand token for setting the span */
  ){
    pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
    pOut->zStart = pOperand->zStart;
    pOut->zEnd = &pPostOp->z[pPostOp->n];
  }                           
}

expr(A) ::= expr(X) ISNULL|NOTNULL(E).   {spanUnaryPostfix(&A,pParse,@E,&X,&E);}
expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}

%include {
  /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
  ** unary TK_ISNULL or TK_NOTNULL expression. */
  static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
    sqlite3 *db = pParse->db;
    if( pA && pY && pY->op==TK_NULL ){
      pA->op = (u16)op;
      sqlite3ExprDelete(db, pA->pRight);
      pA->pRight = 0;
    }
  }
}

//    expr1 IS expr2
//    expr1 IS NOT expr2
//
// If expr2 is NULL then code as TK_ISNULL or TK_NOTNULL.  If expr2
// is any other expression, code as TK_IS or TK_ISNOT.
// 
expr(A) ::= expr(X) IS expr(Y).     {
  spanBinaryExpr(&A,pParse,TK_IS,&X,&Y);
  binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_ISNULL);
}
expr(A) ::= expr(X) IS NOT expr(Y). {
  spanBinaryExpr(&A,pParse,TK_ISNOT,&X,&Y);
  binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_NOTNULL);
}

%include {
  /* Construct an expression node for a unary prefix operator
  */
  static void spanUnaryPrefix(
    ExprSpan *pOut,        /* Write the new expression node here */
    Parse *pParse,         /* Parsing context to record errors */
    int op,                /* The operator */
    ExprSpan *pOperand,    /* The operand */
    Token *pPreOp         /* The operand token for setting the span */
  ){
    pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
    pOut->zStart = pPreOp->z;
    pOut->zEnd = pOperand->zEnd;
  }
}



expr(A) ::= NOT(B) expr(X).    {spanUnaryPrefix(&A,pParse,@B,&X,&B);}
expr(A) ::= BITNOT(B) expr(X). {spanUnaryPrefix(&A,pParse,@B,&X,&B);}
expr(A) ::= MINUS(B) expr(X). [BITNOT]
                               {spanUnaryPrefix(&A,pParse,TK_UMINUS,&X,&B);}
expr(A) ::= PLUS(B) expr(X). [BITNOT]
                               {spanUnaryPrefix(&A,pParse,TK_UPLUS,&X,&B);}

%type between_op {int}
between_op(A) ::= BETWEEN.     {A = 0;}
between_op(A) ::= NOT BETWEEN. {A = 1;}
expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
  ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr);
  pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr);
  A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0);
  if( A.pExpr ){
    A.pExpr->x.pList = pList;
  }else{
    sqlite3ExprListDelete(pParse->db, pList);
  } 
  exprNot(pParse, N, &A.pExpr);
  A.zStart = W.zStart;
  A.zEnd = Y.zEnd;
}
%ifndef SQLITE_OMIT_SUBQUERY
  %type in_op {int}
  in_op(A) ::= IN.      {A = 0;}
  in_op(A) ::= NOT IN.  {A = 1;}
  expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
    if( Y==0 ){
      /* Expressions of the form
      **
      **      expr1 IN ()
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      A.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[N]);
      sqlite3ExprDelete(pParse->db, X.pExpr);
    }else if( Y->nExpr==1 ){
      /* Expressions of the form:
      **
      **      expr1 IN (?1)
      **      expr1 NOT IN (?2)
      **
      ** with exactly one value on the RHS can be simplified to something
      ** like this:
      **
      **      expr1 == ?1
      **      expr1 <> ?2
      **
      ** But, the RHS of the == or <> is marked with the EP_Generic flag
      ** so that it may not contribute to the computation of comparison
      ** affinity or the collating sequence to use for comparison.  Otherwise,
      ** the semantics would be subtly different from IN or NOT IN.
      */
      Expr *pRHS = Y->a[0].pExpr;
      Y->a[0].pExpr = 0;
      sqlite3ExprListDelete(pParse->db, Y);
      /* pRHS cannot be NULL because a malloc error would have been detected
      ** before now and control would have never reached this point */
      if( ALWAYS(pRHS) ){
        pRHS->flags &= ~EP_Collate;
        pRHS->flags |= EP_Generic;
      }
      A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, X.pExpr, pRHS, 0);
    }else{
      A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
      if( A.pExpr ){
        A.pExpr->x.pList = Y;
        sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
      }else{
        sqlite3ExprListDelete(pParse->db, Y);
      }
      exprNot(pParse, N, &A.pExpr);
    }
    A.zStart = X.zStart;
    A.zEnd = &E.z[E.n];
  }
  expr(A) ::= LP(B) select(X) RP(E). {
    A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
    if( A.pExpr ){
      A.pExpr->x.pSelect = X;
      ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
      sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, X);
    }
    A.zStart = B.z;
    A.zEnd = &E.z[E.n];
  }
  expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E).  [IN] {
    A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
    if( A.pExpr ){
      A.pExpr->x.pSelect = Y;
      ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
      sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
    }else{
      sqlite3SelectDelete(pParse->db, Y);
    }
    exprNot(pParse, N, &A.pExpr);
    A.zStart = X.zStart;
    A.zEnd = &E.z[E.n];
  }
  expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
    SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
    A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
    if( A.pExpr ){
#ifdef MAXSCALE
      A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0,0);
#else
      A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
#endif
      ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
      sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
    }else{
      sqlite3SrcListDelete(pParse->db, pSrc);
    }
    exprNot(pParse, N, &A.pExpr);
    A.zStart = X.zStart;
    A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
  }
  expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
    Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
    if( p ){
      p->x.pSelect = Y;
      ExprSetProperty(p, EP_xIsSelect|EP_Subquery);
      sqlite3ExprSetHeightAndFlags(pParse, p);
    }else{
      sqlite3SelectDelete(pParse->db, Y);
    }
    A.zStart = B.z;
    A.zEnd = &E.z[E.n];
  }
%endif SQLITE_OMIT_SUBQUERY

/* CASE expressions */
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
  A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0);
  if( A.pExpr ){
    A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y;
    sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
  }else{
    sqlite3ExprListDelete(pParse->db, Y);
    sqlite3ExprDelete(pParse->db, Z);
  }
  A.zStart = C.z;
  A.zEnd = &E.z[E.n];
}
%type case_exprlist {ExprList*}
%destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
  A = sqlite3ExprListAppend(pParse,X, Y.pExpr);
  A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
}
case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
  A = sqlite3ExprListAppend(pParse,0, Y.pExpr);
  A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
}
%type case_else {Expr*}
%destructor case_else {sqlite3ExprDelete(pParse->db, $$);}
case_else(A) ::=  ELSE expr(X).         {A = X.pExpr;}
case_else(A) ::=  .                     {A = 0;} 
%type case_operand {Expr*}
%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
case_operand(A) ::= expr(X).            {A = X.pExpr;} 
case_operand(A) ::= .                   {A = 0;} 

%type exprlist {ExprList*}
%destructor exprlist {sqlite3ExprListDelete(pParse->db, $$);}
%type nexprlist {ExprList*}
%destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);}

exprlist(A) ::= nexprlist(X).                {A = X;}
exprlist(A) ::= .                            {A = 0;}
nexprlist(A) ::= nexprlist(X) COMMA expr(Y).
    {A = sqlite3ExprListAppend(pParse,X,Y.pExpr);}
nexprlist(A) ::= expr(Y).
    {A = sqlite3ExprListAppend(pParse,0,Y.pExpr);}
%ifdef MAXSCALE
nexprlist(A) ::= expr(Y) AS typename.
    {A = sqlite3ExprListAppend(pParse,0,Y.pExpr);}
nexprlist(A) ::= nexprlist(X) COMMA expr(Y) AS typename.
    {A = sqlite3ExprListAppend(pParse,X,Y.pExpr);}
%endif

///////////////////////////// The CREATE INDEX command ///////////////////////
//
cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
        ON nm(Y) LP sortlist(Z) RP where_opt(W). {
#ifdef MAXSCALE
  mxs_sqlite3CreateIndex(pParse, &X, &D,
                         sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U,
                         &S, W, SQLITE_SO_ASC, NE);
#else
  sqlite3CreateIndex(pParse, &X, &D, 
                     sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U,
                      &S, W, SQLITE_SO_ASC, NE);
#endif
}

%type uniqueflag {int}
uniqueflag(A) ::= UNIQUE.  {A = OE_Abort;}
uniqueflag(A) ::= .        {A = OE_None;}


// The eidlist non-terminal (Expression Id List) generates an ExprList
// from a list of identifiers.  The identifier names are in ExprList.a[].zName.
// This list is stored in an ExprList rather than an IdList so that it
// can be easily sent to sqlite3ColumnsExprList().
//
// eidlist is grouped with CREATE INDEX because it used to be the non-terminal
// used for the arguments to an index.  That is just an historical accident.
//
// IMPORTANT COMPATIBILITY NOTE:  Some prior versions of SQLite accepted
// COLLATE clauses and ASC or DESC keywords on ID lists in inappropriate
// places - places that might have been stored in the sqlite_master schema.
// Those extra features were ignored.  But because they might be in some
// (busted) old databases, we need to continue parsing them when loading
// historical schemas.
//
%type eidlist {ExprList*}
%destructor eidlist {sqlite3ExprListDelete(pParse->db, $$);}
%type eidlist_opt {ExprList*}
%destructor eidlist_opt {sqlite3ExprListDelete(pParse->db, $$);}

%include {
  /* Add a single new term to an ExprList that is used to store a
  ** list of identifiers.  Report an error if the ID list contains
  ** a COLLATE clause or an ASC or DESC keyword, except ignore the
  ** error while parsing a legacy schema.
  */
  static ExprList *parserAddExprIdListTerm(
    Parse *pParse,
    ExprList *pPrior,
    Token *pIdToken,
    int hasCollate,
    int sortOrder
  ){
    ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0);
    if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED)
        && pParse->db->init.busy==0
    ){
      sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"",
                         pIdToken->n, pIdToken->z);
    }
    sqlite3ExprListSetName(pParse, p, pIdToken, 1);
    return p;
  }
} // end %include

eidlist_opt(A) ::= .                         {A = 0;}
eidlist_opt(A) ::= LP eidlist(X) RP.         {A = X;}
eidlist(A) ::= eidlist(X) COMMA nm(Y) collate(C) sortorder(Z).  {
  A = parserAddExprIdListTerm(pParse, X, &Y, C, Z);
}
eidlist(A) ::= nm(Y) collate(C) sortorder(Z). {
  A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z);
}

%type collate {int}
collate(C) ::= .              {C = 0;}
collate(C) ::= COLLATE ids.   {C = 1;}


///////////////////////////// The DROP INDEX command /////////////////////////
//
%ifdef MAXSCALE

%type drop_index_algorithm_option {int}
drop_index_algorithm_option(A) ::= DEFAULT. {A=0;}
drop_index_algorithm_option(A) ::= id. {
  // Here we could verify that the id is "COPY" or "INPLACE"
  A=1;
}

%type drop_index_algorithm {int}
drop_index_algorithm(A) ::= ALGORITHM drop_index_algorithm_option(X). {A=X;}
drop_index_algorithm(A) ::= ALGORITHM EQ drop_index_algorithm_option(X). {A=X;}

%type drop_index_lock_option {int}
drop_index_lock_option(A) ::= DEFAULT. {A=0;}
drop_index_lock_option(A) ::= id. {
  // Here we could verify that the id is "EXCLUSIVE", "NONE" or "SHARED".
  A=4;
}

%type drop_index_lock {int}
drop_index_lock(A) ::= LOCK drop_index_lock_option(X). {A=X;}
drop_index_lock(A) ::= LOCK EQ drop_index_lock_option(X). {A=X;}

%type drop_index_options {int}
drop_index_options(A) ::= . {A=0;}
drop_index_options(A) ::= drop_index_options(X) drop_index_algorithm(Y). {A=X|Y;}
drop_index_options(A) ::= drop_index_options(X) drop_index_lock(Y). {A=X|Y;}

cmd ::= DROP INDEX fullname(X) ON fullname(Y) drop_index_options(Z). {
  mxs_sqlite3DropIndex(pParse, X, Y, Z);
}

%endif
%ifndef MAXSCALE
cmd ::= DROP INDEX ifexists(E) fullname(X).   {sqlite3DropIndex(pParse, X, E);}
%endif

///////////////////////////// The VACUUM command /////////////////////////////
//
%ifndef SQLITE_OMIT_VACUUM
%ifndef SQLITE_OMIT_ATTACH
cmd ::= VACUUM.                {sqlite3Vacuum(pParse);}
cmd ::= VACUUM nm.             {sqlite3Vacuum(pParse);}
%endif  SQLITE_OMIT_ATTACH
%endif  SQLITE_OMIT_VACUUM

///////////////////////////// The PRAGMA command /////////////////////////////
//
%ifndef SQLITE_OMIT_PRAGMA
cmd ::= PRAGMA nm(X) dbnm(Z).                {sqlite3Pragma(pParse,&X,&Z,0,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) EQ nmnum(Y).    {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) LP nmnum(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);}
cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). 
                                             {sqlite3Pragma(pParse,&X,&Z,&Y,1);}
cmd ::= PRAGMA nm(X) dbnm(Z) LP minus_num(Y) RP.
                                             {sqlite3Pragma(pParse,&X,&Z,&Y,1);}

nmnum(A) ::= plus_num(X).             {A = X;}
nmnum(A) ::= nm(X).                   {A = X;}
nmnum(A) ::= ON(X).                   {A = X;}
nmnum(A) ::= DELETE(X).               {A = X;}
nmnum(A) ::= DEFAULT(X).              {A = X;}
%endif SQLITE_OMIT_PRAGMA
%token_class number INTEGER|FLOAT.
plus_num(A) ::= PLUS number(X).       {A = X;}
plus_num(A) ::= number(X).            {A = X;}
minus_num(A) ::= MINUS number(X).     {A = X;}
//////////////////////////// The CREATE TRIGGER command /////////////////////

%ifndef SQLITE_OMIT_TRIGGER

cmd ::= createkw trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
  Token all;
  all.z = A.z;
  all.n = (int)(Z.z - A.z) + Z.n;
#ifdef MAXSCALE
  mxs_sqlite3FinishTrigger(pParse, S, &all);
#else
  sqlite3FinishTrigger(pParse, S, &all);
#endif
}

trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z) 
                    trigger_time(C) trigger_event(D)
                    ON fullname(E) foreach_clause when_clause(G). {
#ifdef MAXSCALE
  mxs_sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR);
#else
  sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR);
#endif
  A = (Z.n==0?B:Z);
}

%type trigger_time {int}
trigger_time(A) ::= BEFORE.      { A = TK_BEFORE; }
trigger_time(A) ::= AFTER.       { A = TK_AFTER;  }
trigger_time(A) ::= INSTEAD OF.  { A = TK_INSTEAD;}
trigger_time(A) ::= .            { A = TK_BEFORE; }

%type trigger_event {struct TrigEvent}
%destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);}
trigger_event(A) ::= DELETE|INSERT(OP).       {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE(OP).              {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE OF idlist(X). {A.a = TK_UPDATE; A.b = X;}

foreach_clause ::= .
foreach_clause ::= FOR EACH ROW.

%type when_clause {Expr*}
%destructor when_clause {sqlite3ExprDelete(pParse->db, $$);}
when_clause(A) ::= .             { A = 0; }
when_clause(A) ::= WHEN expr(X). { A = X.pExpr; }

%type trigger_cmd_list {TriggerStep*}
%destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);}
trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. {
  assert( Y!=0 );
  Y->pLast->pNext = X;
  Y->pLast = X;
  A = Y;
}
trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. { 
  assert( X!=0 );
  X->pLast = X;
  A = X;
}

// Disallow qualified table names on INSERT, UPDATE, and DELETE statements
// within a trigger.  The table to INSERT, UPDATE, or DELETE is always in 
// the same database as the table that the trigger fires on.
//
%type trnm {Token}
trnm(A) ::= nm(X).   {A = X;}
trnm(A) ::= nm DOT nm(X). {
  A = X;
  sqlite3ErrorMsg(pParse, 
        "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
        "statements within triggers");
}

// Disallow the INDEX BY and NOT INDEXED clauses on UPDATE and DELETE
// statements within triggers.  We make a specific error message for this
// since it is an exception to the default grammar rules.
//
tridxby ::= .
tridxby ::= INDEXED BY nm. {
  sqlite3ErrorMsg(pParse,
        "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
tridxby ::= NOT INDEXED. {
  sqlite3ErrorMsg(pParse,
        "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}



%type trigger_cmd {TriggerStep*}
%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);}
// UPDATE 
trigger_cmd(A) ::=
   UPDATE orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z).  
   { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); }

// INSERT
trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) idlist_opt(F) select(S).
               {A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);}

// DELETE
trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y).
               {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);}

// SELECT
trigger_cmd(A) ::= select(X).  {A = sqlite3TriggerSelectStep(pParse->db, X); }

// The special RAISE expression that may occur in trigger programs
expr(A) ::= RAISE(X) LP IGNORE RP(Y).  {
  A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); 
  if( A.pExpr ){
    A.pExpr->affinity = OE_Ignore;
  }
  A.zStart = X.z;
  A.zEnd = &Y.z[Y.n];
}
%ifndef MAXSCALE
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y).  {
  A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z); 
  if( A.pExpr ) {
    A.pExpr->affinity = (char)T;
  }
  A.zStart = X.z;
  A.zEnd = &Y.z[Y.n];
}
%endif
%endif  !SQLITE_OMIT_TRIGGER

%ifndef MAXSCALE
%type raisetype {int}
raisetype(A) ::= ROLLBACK.  {A = OE_Rollback;}
raisetype(A) ::= ABORT.     {A = OE_Abort;}
raisetype(A) ::= FAIL.      {A = OE_Fail;}
%endif


////////////////////////  DROP TRIGGER statement //////////////////////////////
%ifndef SQLITE_OMIT_TRIGGER
cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). {
  sqlite3DropTrigger(pParse,X,NOERR);
}
%endif  !SQLITE_OMIT_TRIGGER

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
%ifndef SQLITE_OMIT_ATTACH
cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). {
  sqlite3Attach(pParse, F.pExpr, D.pExpr, K);
}
cmd ::= DETACH database_kw_opt expr(D). {
  sqlite3Detach(pParse, D.pExpr);
}

%type key_opt {Expr*}
%destructor key_opt {sqlite3ExprDelete(pParse->db, $$);}
key_opt(A) ::= .                     { A = 0; }
key_opt(A) ::= KEY expr(X).          { A = X.pExpr; }

database_kw_opt ::= DATABASE.
database_kw_opt ::= .
%endif SQLITE_OMIT_ATTACH

////////////////////////// REINDEX collation //////////////////////////////////
%ifndef SQLITE_OMIT_REINDEX
cmd ::= REINDEX.                {sqlite3Reindex(pParse, 0, 0);}
cmd ::= REINDEX nm(X) dbnm(Y).  {sqlite3Reindex(pParse, &X, &Y);}
%endif  SQLITE_OMIT_REINDEX

/////////////////////////////////// ANALYZE ///////////////////////////////////
%ifndef SQLITE_OMIT_ANALYZE
%ifdef MAXSCALE
analyze_options ::= .
analyze_options ::= NO_WRITE_TO_BINLOG.
analyze_options ::= LOCAL.

cmd ::= ANALYZE analyze_options TABLE fullnames(X).  {mxs_sqlite3Analyze(pParse, X);}
%endif
%ifndef MAXSCALE
cmd ::= ANALYZE.                {sqlite3Analyze(pParse, 0, 0);}
cmd ::= ANALYZE nm(X) dbnm(Y).  {sqlite3Analyze(pParse, &X, &Y);}
%endif
%endif

//////////////////////// ALTER TABLE table ... ////////////////////////////////
%ifndef SQLITE_OMIT_ALTERTABLE
%ifndef MAXSCALE
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
  sqlite3AlterRenameTable(pParse,X,&Z);
}

cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). {
  sqlite3AlterFinishAddColumn(pParse, &Y);
}
%endif
%ifdef MAXSCALE
first_opt ::= .
first_opt ::= FIRST.

as_or_to_opt ::= .
as_or_to_opt ::= AS.
as_or_to_opt ::= TO.

cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y) first_opt. {
  mxs_sqlite3AlterFinishAddColumn(pParse, &Y);
}

cmd ::= ALTER TABLE fullname(X) ENABLE KEYS. {
  maxscaleAlterTable(pParse,MXS_ALTER_ENABLE_KEYS,X,0);
}

cmd ::= ALTER TABLE fullname(X) DISABLE KEYS. {
  maxscaleAlterTable(pParse,MXS_ALTER_DISABLE_KEYS,X,0);
}

cmd ::= ALTER TABLE fullname(X) RENAME as_or_to_opt nm(Z). {
  maxscaleAlterTable(pParse,MXS_ALTER_RENAME,X,&Z);
}
%endif
add_column_fullname ::= fullname(X). {
  disableLookaside(pParse);
#ifdef MAXSCALE
  mxs_sqlite3AlterBeginAddColumn(pParse, X);
#else
  sqlite3AlterBeginAddColumn(pParse, X);
#endif
}
kwcolumn_opt ::= .
kwcolumn_opt ::= COLUMNKW.
%endif  SQLITE_OMIT_ALTERTABLE

//////////////////////// CREATE VIRTUAL TABLE ... /////////////////////////////
%ifndef SQLITE_OMIT_VIRTUALTABLE
cmd ::= create_vtab.                       {sqlite3VtabFinishParse(pParse,0);}
cmd ::= create_vtab LP vtabarglist RP(X).  {sqlite3VtabFinishParse(pParse,&X);}
create_vtab ::= createkw VIRTUAL TABLE ifnotexists(E)
                nm(X) dbnm(Y) USING nm(Z). {
    sqlite3VtabBeginParse(pParse, &X, &Y, &Z, E);
}
vtabarglist ::= vtabarg.
vtabarglist ::= vtabarglist COMMA vtabarg.
vtabarg ::= .                       {sqlite3VtabArgInit(pParse);}
vtabarg ::= vtabarg vtabargtoken.
vtabargtoken ::= ANY(X).            {sqlite3VtabArgExtend(pParse,&X);}
vtabargtoken ::= lp anylist RP(X).  {sqlite3VtabArgExtend(pParse,&X);}
lp ::= LP(X).                       {sqlite3VtabArgExtend(pParse,&X);}
anylist ::= .
anylist ::= anylist LP anylist RP.
anylist ::= anylist ANY.
%endif  SQLITE_OMIT_VIRTUALTABLE


//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
%type with {With*}
%type wqlist {With*}
%destructor with {sqlite3WithDelete(pParse->db, $$);}
%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}

with(A) ::= . {A = 0;}
%ifndef SQLITE_OMIT_CTE
with(A) ::= WITH wqlist(W).              { A = W; }
with(A) ::= WITH RECURSIVE wqlist(W).    { A = W; }

wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
  A = sqlite3WithAdd(pParse, 0, &X, Y, Z);
}
wqlist(A) ::= wqlist(W) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
  A = sqlite3WithAdd(pParse, W, &X, Y, Z);
}
%endif  SQLITE_OMIT_CTE

%ifdef MAXSCALE
/*
** MaxScale additions.
**
** New grammar rules made for MaxScale follow here.
**
*/

cmd ::= do.

do ::= DO nexprlist(X). {
  maxscaleDo(pParse, X);
}

%type type_options {int}
type_options(A) ::= . {A=0;}
type_options(A) ::= type_options UNSIGNED. {A|=1;}
type_options(A) ::= type_options ZEROFILL. {A|=2;}
type_options(A) ::= type_options BINARY. {A|=4;}
type_options(A) ::= type_options CHARACTER SET ids. {A|=8;}
type_options(A) ::= type_options CHARSET ids. {A|=8;}

// deferred_id is used instead of id before the token_class id has been defined.
deferred_id(A) ::= id(X). {A=X;}

as_opt ::= .
as_opt ::= AS.

eq_opt ::= .
eq_opt ::= EQ.

default_opt ::= .
default_opt ::= DEFAULT.

////////////////////////// DROP DATABASE statement /////////////////////////////////////
//
cmd ::= DROP DATABASE ifexists id(X). {
    maxscaleDrop(pParse, MXS_DROP_DATABASE, &X, NULL);
}

//////////////////////// CALL statement ////////////////////////////////////
//
cmd ::= call.

%type call_args_opt {ExprList*}
%destructor call_args_opt {sqlite3ExprListDelete(pParse->db, $$);}
call_args_opt(A) ::= . {A=0;}
call_args_opt(A) ::= LP exprlist(X) RP. {A=X;}

call ::= CALL fullname(X) call_args_opt(Y). {
    maxscaleCall(pParse, X, Y);
}

//////////////////////// DROP FUNCTION statement ////////////////////////////////////
//
cmd ::= DROP FUNCTION_KW ifexists nm(X). {
  maxscaleDrop(pParse, MXS_DROP_FUNCTION, NULL, &X);
}

//////////////////////// The CHECK TABLE statement ////////////////////////////////////
//
cmd ::= check.

// FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED
check_option ::= FOR id.
check_option ::= QUICK.
check_option ::= id.

check_options ::= check_option.
check_options ::= check_options check_option.

check_options_opt ::= .
check_options_opt ::= check_options.


check ::= CHECK TABLE fullnames(X) check_options_opt. {
  maxscaleCheckTable(pParse, X);
}

//////////////////////// The FLUSH statement ////////////////////////////////////
//
cmd ::= flush.

flush ::= FLUSH STATUS(X).
{
  maxscaleFlush(pParse, &X);
}

flush ::= FLUSH nm(X).
{
  maxscaleFlush(pParse, &X);
}

//////////////////////// The GRANT & REVOKE statements ////////////////////////////////////
//
cmd ::= grant.

grant ::= GRANT. {
    maxscalePrivileges(pParse, TK_GRANT);
}

cmd ::= revoke.

revoke ::= REVOKE. {
    maxscalePrivileges(pParse, TK_REVOKE);
}

//////////////////////// The HANDLER statement ////////////////////////////////////
//
cmd ::= handler.

handler ::= HANDLER fullname(X) OPEN as_opt nm(Y). {
  maxscaleHandler(pParse, MXS_HANDLER_OPEN, X, &Y);
}

handler ::= HANDLER nm(X) CLOSE. {
  maxscaleHandler(pParse, MXS_HANDLER_CLOSE, 0, &X);
}

// TODO: Rest of HANDLER commands.

//////////////////////// The LOAD DATA INFILE statement ////////////////////////////////////
//

%type ld_local_opt {int}

cmd ::= load_data.

ld_priority_opt ::= .
ld_priority_opt ::= LOW_PRIORITY.
ld_priority_opt ::= CONCURRENT.

ld_local_opt(A) ::= .      {A = 0;}
ld_local_opt(A) ::= LOCAL. {A = 1;}

ld_charset_opt ::= .
ld_charset_opt ::= CHARACTER SET ids.

load_data ::= LOAD DATA ld_priority_opt ld_local_opt(Y)
              INFILE STRING ignore_or_replace_opt
              INTO TABLE fullname(X)
              /* ld_partition_opt */
              ld_charset_opt
              /* ld_fields_opt */
              /* ld_ignore_opt */
              /* ld_col_name_or_user_var_opt */
              /* ld_set */.
{
    maxscaleLoadData(pParse, X, Y);
}

//////////////////////// The LOCK/UNLOCK statement ////////////////////////////////////
//
cmd ::= lock.

lock ::= LOCK table_or_tables lock_target(X).{
  maxscaleLock(pParse, MXS_LOCK_LOCK, X);
}

%type lock_target {SrcList*}
%destructor lock_target {sqlite3SrcListDelete(pParse->db, $$);}

lock_target(A) ::= table_factor(X) lock_type. {
  A = X;
}
lock_target(A) ::= lock_target(X) COMMA table_factor(Y). {
  A = sqlite3SrcListCat(pParse->db, X, Y);
}

%type lock_type {int}

lock_type(A) ::= READ. { A = 1; }
lock_type(A) ::= READ LOCAL. { A = 3; }
lock_type(A) ::= WRITE. { A = 4; }
lock_type(A) ::= LOW_PRIORITY WRITE. { A = 12; }


cmd ::= unlock.

unlock ::= UNLOCK TABLES. {
  maxscaleLock(pParse, MXS_LOCK_UNLOCK, 0);
}

//////////////////////// PREPARE and EXECUTE statements ////////////////////////////////////
//
cmd ::= prepare.
cmd ::= execute.
cmd ::= deallocate.

prepare ::= PREPARE nm(X) FROM expr(Y).
{
  maxscalePrepare(pParse, &X, Y.pExpr);
}

%type execute_variable {int}
execute_variable(A) ::= INTEGER.  {A=0;} // For Oracle
execute_variable(A) ::= VARIABLE. {A=QUERY_TYPE_USERVAR_READ;}

%type execute_variables {int}
execute_variables(A) ::= execute_variable(X). {A=X;}
execute_variables(A) ::= execute_variables(X) COMMA execute_variable(Y). {
  A = X|Y;
}

%type execute_variables_opt {int}

execute_variables_opt(A) ::= .                           {A=0;}
execute_variables_opt(A) ::= USING execute_variables(X). {A=X;}

execute ::= EXECUTE nm(X) execute_variables_opt(Y). {
    maxscaleExecute(pParse, &X, Y);
}

execute ::= EXECUTE id(X) expr(Y) execute_variables_opt(Z). {
    maxscaleExecuteImmediate(pParse, &X, &Y, Z);
}

dod ::= DEALLOCATE.
dod ::= DROP.

deallocate ::= dod PREPARE nm(X). {
  maxscaleDeallocate(pParse, &X);
}

//////////////////////// RENAME statement ////////////////////////////////////
//
cmd ::= rename.

%type table_to_rename {SrcList*}
%destructor table_to_rename {sqlite3SrcListDelete(pParse->db, $$);}

table_to_rename(A) ::= fullname(X) TO fullname(Y). {
  A = sqlite3SrcListCat(pParse->db, X, Y);
}

%type tables_to_rename {SrcList*}
%destructor tables_to_rename {sqlite3SrcListDelete(pParse->db, $$);}

tables_to_rename(A) ::= table_to_rename(X). {
  A = X;
}
tables_to_rename(A) ::= tables_to_rename(X) COMMA table_to_rename(Y).
{
  A = sqlite3SrcListCat(pParse->db, X, Y);
}

rename ::= RENAME TABLE tables_to_rename(X). {
  maxscaleRenameTable(pParse, X);
}

//////////////////////// The RESET statement ////////////////////////////////////
//
cmd ::= RESET QUERY CACHE. {
  maxscaleReset(pParse, MXS_RESET_QUERY_CACHE);
}

//////////////////////// The SET statement ////////////////////////////////////
//
%type set_scope {int}

set_scope(A) ::= .           { A = 0; }
set_scope(A) ::= GLOBAL(X).  { A = @X; }
set_scope(A) ::= SESSION(X). { A = @X; }
set_scope(A) ::= LOCAL.      { A = TK_SESSION; }

%type variable {ExprSpan}
%destructor variable { sqlite3ExprDelete(pParse->db, $$.pExpr); }

%type variable_head {ExprSpan}
%destructor variable_head { sqlite3ExprDelete(pParse->db, $$.pExpr); }

%type variable_tail {ExprSpan}
%destructor variable_tail { sqlite3ExprDelete(pParse->db, $$.pExpr); }

variable_head(A) ::= VARIABLE(X). {
  A.pExpr = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, &X);
  spanSet(&A, &X, &X);
}

variable_head(A) ::= id(X). {
  A.pExpr = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  spanSet(&A, &X, &X);
}

variable_tail(A) ::= DOT(D) id(X). {
  Expr* pName = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, 0, pName, 0);
  spanSet(&A, &D, &X);
}

variable_tail(A) ::= variable_tail(X) DOT id(Y). {
  assert(!X.pExpr->pLeft);
  X.pExpr->pLeft = X.pExpr->pRight;
  Expr* pName = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
  X.pExpr->pRight = pName;
  A = X;
  A.zStart = X.zStart;
  A.zEnd = X.zEnd;
}

variable(A) ::= variable_head(X). {
  A = X;
}

variable(A) ::= variable_head(X) variable_tail(Y). {
  A.pExpr = sqlite3PExpr(pParse, TK_DOT, X.pExpr, Y.pExpr, 0);
  A.zStart = X.zStart;
  A.zEnd = Y.zEnd;
}

%type variable_assignment {Expr*}
%destructor variable_assignment {sqlite3ExprDelete(pParse->db, $$);}

variable_assignment(A) ::= set_scope(Z) variable(X) EQ expr(Y). {
  A = sqlite3PExpr(pParse, TK_EQ, X.pExpr, Y.pExpr, 0);
  maxscaleSetVariable(pParse, Z, A);
}

variable_assignment(A) ::= set_scope(Z) variable(X) EQ ON. {
  Expr* pOn = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
  pOn->u.iValue = 1;
  A = sqlite3PExpr(pParse, TK_EQ, X.pExpr, pOn, 0);
  maxscaleSetVariable(pParse, Z, A);
}

variable_assignment(A) ::= set_scope(Z) variable(X) EQ ALL. {
  Expr* pOn = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
  pOn->u.iValue = 1;
  A = sqlite3PExpr(pParse, TK_EQ, X.pExpr, pOn, 0);
  maxscaleSetVariable(pParse, Z, A);
}

set_names_arg ::= ids.             // 'charset_name'
set_names_arg ::= ids COLLATE ids. // 'charset_name' COLLATE 'collation_name'
set_names_arg ::= DEFAULT.

variable_assignment(A) ::= NAMES set_names_arg. {
  A = sqlite3PExpr(pParse, TK_NAMES, 0, 0, 0);
}

set_character_set_arg ::= ids.
set_character_set_arg ::= DEFAULT.

variable_assignment(A) ::= CHARACTER SET set_character_set_arg. {
  A = sqlite3PExpr(pParse, TK_CHARACTER, 0, 0, 0);
}

%type variable_assignments {ExprList*}
%destructor variable_assignments {sqlite3ExprListDelete(pParse->db, $$);}

variable_assignments(A) ::= variable_assignment(X). {
  A = sqlite3ExprListAppend(pParse, 0, X);
}

variable_assignments(A) ::= variable_assignments(X) COMMA variable_assignment(Y). {
  A = sqlite3ExprListAppend(pParse, X, Y);
}

cmd ::= SET variable_assignments(Y). {
  maxscaleSet(pParse, 0, MXS_SET_VARIABLES, Y);
}

user ::= STRING.
user ::= STRING VARIABLE. // 'user'@'host' will be parsed as STRING VARIABLE

for_user ::= FOR user.

for_user_opt ::= .
for_user_opt ::= for_user.

password_value ::= PASSWORD LP STRING RP.
password_value ::= OLD_PASSWORD LP STRING RP.
password_value ::= STRING.

cmd ::= SET PASSWORD for_user_opt EQ password_value. {
  maxscaleSetPassword(pParse);
}

%type trx_access_mode {int}

trx_access_mode(A) ::= READ WRITE. {A = TK_WRITE;}
trx_access_mode(A) ::= READ ONLY.  {A = TK_READ;}

trx_isolation ::= ISOLATION LEVEL isolation_type.

isolation_type ::= REPEATABLE READ.
isolation_type ::= READ COMMITTED.
isolation_type ::= READ UNCOMMITTED.
isolation_type ::= SERIALIZABLE.

%type transaction_characteristics {int}

// The syntax for SET TRANSACTION allows only one isolation level and one
// access mode. They can be in either order but they must repeat only
// once.

transaction_characteristics(A) ::= trx_isolation.                          {A = 0;}
transaction_characteristics(A) ::= trx_isolation COMMA trx_access_mode(X). {A = X;}
transaction_characteristics(A) ::= trx_access_mode(X).                     {A = X;}
transaction_characteristics(A) ::= trx_access_mode(X) COMMA trx_isolation. {A = X;}

cmd ::= SET set_scope(X) TRANSACTION transaction_characteristics(Y). {
  maxscaleSetTransaction(pParse, X, Y);
}

// variable_assignent[s] cannot be used with SET STATEMENT as that would,
// due to the maxscaleSetVariable() calls, cause wrong bits to be turned on.
%type statement_variable_assignment {Expr*}
%destructor statement_variable_assignment {sqlite3ExprDelete(pParse->db, $$);}

statement_variable_assignment(A) ::= variable(X) EQ expr(Y). {
  A = sqlite3PExpr(pParse, TK_EQ, X.pExpr, Y.pExpr, 0);
}

%type statement_variable_assignments {ExprList*}
%destructor statement_variable_assignments {sqlite3ExprListDelete(pParse->db, $$);}

statement_variable_assignments(A) ::= statement_variable_assignment(X). {
  A = sqlite3ExprListAppend(pParse, 0, X);
}

statement_variable_assignments(A) ::=
  statement_variable_assignments(X) COMMA statement_variable_assignment(Y). {
  A = sqlite3ExprListAppend(pParse, X, Y);
}

cmd ::= SET STATEMENT statement_variable_assignments(X) FOR cmd. {
  // The parsing of cmd will cause the relevant maxscale-callback to
  // be called, so we neither need to call it here, nor free cmd (as
  // it will be freed by that callback). The variable definitions we
  // just throw away, as they are of no interest.
  sqlite3ExprListDelete(pParse->db, X);
}

role ::= STRING.
role ::= id.     // Covers NONE as well.

// Covers '... FOR 'user'@'host' as well. Stmt will be partial parsed, but type will be correct.
cmd ::= SET DEFAULT ROLE role. {
  maxscaleSet(pParse, 0, MXS_SET_DEFAULT_ROLE, 0);
}

//////////////////////// The USE statement ////////////////////////////////////
//
cmd ::= use(X). {
  maxscaleUse(pParse, &X);
}

%type use {Token}

use(A) ::= USE id(X). {A = X;}

//////////////////////// The SHOW statement ////////////////////////////////////
//

cmd ::= show(X). {
  maxscaleShow(pParse, &X);
}

from_or_in ::= FROM.
from_or_in ::= IN.

from_or_in_db_opt(A) ::= . { A.z = 0; A.n = 0; }
from_or_in_db_opt(A) ::= FROM nm(X). { A = X; }
from_or_in_db_opt(A) ::= IN nm(X). { A = X; }

// sqlite returns FULL (as well as CROSS, INNER, LEFT,
// NATURAL, OUTER and RIGHT) as JOIN_KW.
%type full_opt {u32}
full_opt(A) ::= . { A = 0; }
full_opt(A) ::= JOIN_KW. { A = MXS_SHOW_COLUMNS_FULL; }

like_or_where_opt ::= .
like_or_where_opt ::= LIKE_KW ids.
like_or_where_opt ::= WHERE expr.

%type show {MxsShow}

columns_or_fields ::= COLUMNS.
columns_or_fields ::= FIELDS.

show(A) ::= SHOW full_opt(X) columns_or_fields from_or_in nm(Y) dbnm(Z) from_or_in_db_opt(W) like_or_where_opt . {
  A.what = MXS_SHOW_COLUMNS;
  A.data = X;
  if (Z.z) {
      A.pName = &Z;
      A.pDatabase = &Y;
  }
  else if (W.z) {
      A.pName = &Y;
      A.pDatabase = &W;
  }
  else {
      A.pName = &Y;
      A.pDatabase = NULL;
  }
}

show(A) ::= SHOW CREATE TABLE nm(X) dbnm(Y). {
  A.what = MXS_SHOW_CREATE_TABLE;
  A.data = 0;
  if (Y.z) {
      A.pName = &Y;
      A.pDatabase = &X;
  }
  else {
      A.pName = &X;
      A.pDatabase = NULL;
  }
}

show(A) ::= SHOW CREATE VIEW nm(X) dbnm(Y). {
  A.what = MXS_SHOW_CREATE_VIEW;
  A.data = 0;
  if (Y.z) {
      A.pName = &Y;
      A.pDatabase = &X;
  }
  else {
      A.pName = &X;
      A.pDatabase = NULL;
  }
}

show(A) ::= SHOW CREATE SEQUENCE nm(X) dbnm(Y). {
  A.what = MXS_SHOW_CREATE_SEQUENCE;
  A.data = 0;
  if (Y.z) {
      A.pName = &Y;
      A.pDatabase = &X;
  }
  else {
      A.pName = &X;
      A.pDatabase = NULL;
  }
}

show(A) ::= SHOW DATABASES_KW like_or_where_opt. {
  A.what = MXS_SHOW_DATABASES;
  A.data = 0;
  A.pName = NULL;
  A.pDatabase = NULL;
}

show(A) ::= SHOW ALL id STATUS. { // SHOW ALL SLAVES STATUS
  A.what = MXS_SHOW_STATUS;
  A.data = MXS_SHOW_STATUS_ALL_SLAVES;
  A.pName = NULL;
  A.pDatabase = NULL;
}

show(A) ::= SHOW MASTER STATUS. {
  A.what = MXS_SHOW_STATUS;
  A.data = MXS_SHOW_STATUS_MASTER;
  A.pName = NULL;
  A.pDatabase = NULL;
}

show(A) ::= SHOW SLAVE STATUS. {
  A.what = MXS_SHOW_STATUS;
  A.data = MXS_SHOW_STATUS_SLAVE;
  A.pName = NULL;
  A.pDatabase = NULL;
}

%type index_indexes_keys {int}

index_indexes_keys(A) ::= INDEX. {A = MXS_SHOW_INDEX;}
index_indexes_keys(A) ::= INDEXES. {A = MXS_SHOW_INDEXES;}
index_indexes_keys(A) ::= KEYS. {A = MXS_SHOW_KEYS;}

show(A) ::= SHOW index_indexes_keys(X) from_or_in nm(Y) dbnm(Z) from_or_in_db_opt where_opt . {
  A.what = X;
  A.data = 0;
  if (Z.z) {
      A.pName = &Z;
      A.pDatabase = &Y;
  }
  else {
      A.pName = &Y;
      A.pDatabase = NULL;
  }
}

%type global_session_local_opt {int}
global_session_local_opt(A) ::= .        {A=MXS_SHOW_VARIABLES_UNSPECIFIED;}
global_session_local_opt(A) ::= GLOBAL.  {A=MXS_SHOW_VARIABLES_GLOBAL;}
global_session_local_opt(A) ::= LOCAL.   {A=MXS_SHOW_VARIABLES_SESSION;}
global_session_local_opt(A) ::= SESSION. {A=MXS_SHOW_VARIABLES_SESSION;}

show(A) ::= SHOW global_session_local_opt(X) STATUS like_or_where_opt. {
  A.what = MXS_SHOW_STATUS;
  A.data = X;
  A.pName = NULL;
  A.pDatabase = NULL;
}

show(A) ::= SHOW full_opt(X) TABLES from_or_in_db_opt(Y) like_or_where_opt. {
  A.what = MXS_SHOW_TABLES;
  A.data = X;
  A.pDatabase = &Y;
  A.pName = NULL;
}

show(A) ::= SHOW TABLE STATUS from_or_in_db_opt(X) like_or_where_opt. {
  A.what = MXS_SHOW_TABLE_STATUS;
  A.data = 0;
  A.pDatabase = &X;
  A.pName = NULL;
}

show(A) ::= SHOW global_session_local_opt(X) VARIABLES like_or_where_opt. {
  A.what = MXS_SHOW_VARIABLES;
  A.data = X;
  A.pName = NULL;
  A.pDatabase = NULL;
}

show_warnings_options ::= .
show_warnings_options ::= LIMIT INTEGER.
show_warnings_options ::= LIMIT INTEGER COMMA INTEGER.

show(A) ::= SHOW WARNINGS show_warnings_options. {
   A.what = MXS_SHOW_WARNINGS;
   A.data = 0;
   A.pName = NULL;
   A.pDatabase = NULL;
}

//////////////////////// The START TRANSACTION statement ////////////////////////////////////
//

%type start_transaction_characteristic {int}

start_transaction_characteristic(A) ::= READ WRITE. {
  A = QUERY_TYPE_WRITE;
}

start_transaction_characteristic(A) ::= READ ONLY. {
  A = QUERY_TYPE_READ;
}

start_transaction_characteristic(A) ::= WITH id id. { // WITH CONSISTENT SNAPSHOT
  A = 0;
}

%type start_transaction_characteristics {int}

start_transaction_characteristics(A) ::= .
{
  A = 0;
}

start_transaction_characteristics(A) ::= start_transaction_characteristic(X).
{
  A = X;
}

start_transaction_characteristics(A) ::=
    start_transaction_characteristics(X) COMMA start_transaction_characteristic(Y). {
  A = X | Y;
}

cmd ::= START TRANSACTION start_transaction_characteristics(X). {
  mxs_sqlite3BeginTransaction(pParse, MXS_BEGIN_TRANSACTION, TK_START, X);
}

//////////////////////// The XA statement ////////////////////////////////////
//

// The XA transaction ID consists of two strings and one integer with only the
// first string being mandatory.
xid ::= STRING.
xid ::= STRING COMMA STRING.
xid ::= STRING COMMA STRING COMMA INTEGER.

xa_start_opt ::= .
xa_start_opt ::= JOIN.
xa_start_opt ::= RESUME.

xa_start ::= START.
xa_start ::= BEGIN.

cmd ::= XA xa_start xid xa_start_opt. {
  mxs_sqlite3BeginTransaction(pParse, MXS_BEGIN_TRANSACTION, TK_START, 0);
}

xa_end_opt ::= .
xa_end_opt ::= SUSPEND.
xa_end_opt ::= SUSPEND FOR MIGRATE.

cmd ::= XA END xid xa_end_opt. {
  mxs_sqlite3CommitTransaction(pParse);
}

//////////////////////// The TRUNCATE statement ////////////////////////////////////
//

table_opt ::= .
table_opt ::= TABLE.

cmd ::= TRUNCATE table_opt nm(X) dbnm(Y). {
  Token* pName;
  Token* pDatabase;
  if (Y.z) {
    pDatabase = &X;
    pName = &Y;
  }
  else {
    pDatabase = NULL;
    pName = &X;
  }

  maxscaleTruncate(pParse, pDatabase, pName);
}

//////////////////////// OPTIMIZE statement ////////////////////////////////////
//
cmd ::= optimize(X). {
    maxscaleOptimize(pParse, X);
}

%type optimize {SrcList*}
%destructor optimize {sqlite3SrcListDelete(pParse->db, $$);}

optimize_arg1_opt ::= .
optimize_arg1_opt ::= LOCAL.
optimize_arg1_opt ::= NO_WRITE_TO_BINLOG.

optimize_arg2_opt ::= .
optimize_arg2_opt ::= NOWAIT.
optimize_arg2_opt ::= WAIT INTEGER.

optimize(A) ::= OPTIMIZE optimize_arg1_opt TABLE fullnames(X) optimize_arg2_opt. {
    A = X;
}

//////////////////////// KILL statement ////////////////////////////////////
//

cmd ::= kill(X). {
    maxscaleKill(pParse, &X);
}

%type kill {MxsKill}

%type kill_hardness_opt {int}
kill_hardness_opt(A) ::= .     {A = 0;}
kill_hardness_opt(A) ::= HARD. {A = 0;}
kill_hardness_opt(A) ::= SOFT. {A = 1;}

%type kill_id_type_opt {mxs_kill_type_t}
kill_id_type_opt(A) ::= .           {A = MXS_KILL_TYPE_CONNECTION;}
kill_id_type_opt(A) ::= CONNECTION. {A = MXS_KILL_TYPE_CONNECTION;}
kill_id_type_opt(A) ::= QUERY.      {A = MXS_KILL_TYPE_QUERY;}
kill_id_type_opt(A) ::= QUERY ID.   {A = MXS_KILL_TYPE_QUERY_ID;}

%type kill_user_type_opt {mxs_kill_type_t}
kill_user_type_opt(A) ::= .           {A = MXS_KILL_TYPE_CONNECTION;}
kill_user_type_opt(A) ::= CONNECTION. {A = MXS_KILL_TYPE_CONNECTION;}
kill_user_type_opt(A) ::= QUERY.      {A = MXS_KILL_TYPE_QUERY;}

kill(A) ::= KILL kill_hardness_opt(X) kill_id_type_opt(Y) INTEGER(Z). {
    A.user = 0;
    A.soft = X;
    A.type = Y;
    A.pTarget = &Z;
}

kill(A) ::= KILL kill_hardness_opt(X) kill_user_type_opt(Y) USER STRING(Z). {
    A.user = 1;
    A.soft = X;
    A.type = Y;
    A.pTarget = &Z;
}

//////////////////////// ORACLE Assignment ////////////////////////////////////
//
oracle_assignment ::= id(X) EQ expr(Y). {
    maxscaleOracleAssign(pParse, &X, Y.pExpr);
}

//////////////////////// ORACLE CREATE SEQUENCE ////////////////////////////////////
//
cmd ::= CREATE SEQUENCE nm(X) dbnm(Y).{ // CREATE SEQUENCE db
    Token* pDatabase;
    Token* pTable;
    if (Y.z)
    {
        pDatabase = &X;
        pTable = &Y;
    }
    else
    {
        pDatabase = NULL;
        pTable = &X;
    }
    maxscaleCreateSequence(pParse, pDatabase, pTable);
}

//////////////////////// ORACLE CREATE SEQUENCE ////////////////////////////////////
//
cmd ::= DROP SEQUENCE nm(X) dbnm(Y).{ // CREATE SEQUENCE db
    Token* pDatabase;
    Token* pTable;
    if (Y.z)
    {
        pDatabase = &X;
        pTable = &Y;
    }
    else
    {
        pDatabase = NULL;
        pTable = &X;
    }
    maxscaleDrop(pParse, MXS_DROP_SEQUENCE, pDatabase, pTable);
}

//////////////////////// ORACLE DECLARE ////////////////////////////////////
//
cmd ::= DECLARE. {
    maxscaleDeclare(pParse);
}

%endif

%include {

static Expr* maxscale_create_pseudo_limit(Parse* pParse, Token* pToken, ExprSpan* pLimit)
{
    // sqlite3 does not accept a ORDER BY without LIMIT, but MariaDB
    // does. Thus, to make sqlite3LimitWhere return non-NULL we need
    // to inject a LIMIT if there is none. We use a value of -1 to
    // tell update_field_infos_from_select() that this LIMIT should
    // not be counted as a limiting clause.
    static char one[] = "-1";
    pToken->z = one;
    pToken->n = 1;
    spanExpr(pLimit, pParse, TK_INTEGER, pToken);
    return pLimit->pExpr;
}

}
